+++ /dev/null
-
- GNU LIBRARY GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL. It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it. You can use it for
-your libraries, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
- Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library. If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-\f
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software. To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
- Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs. This
-license, the GNU Library General Public License, applies to certain
-designated libraries. This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
- The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it. Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program. However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
- Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries. We
-concluded that weaker conditions might promote sharing better.
-
- However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves. This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them. (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.) The hope is that this
-will lead to faster development of free libraries.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, while the latter only
-works together with the library.
-
- Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-\f
- GNU LIBRARY GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License"). Each licensee is
-addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-\f
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-\f
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-\f
- 6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- c) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- d) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-\f
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-\f
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-\f
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-\f
- Appendix: How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
--- /dev/null
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
--- /dev/null
+MIT License
+
+Copyright (c) 1999, Frank Warmerdam
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
-This is a subset of Shapelib v1.5.0 from http://shapelib.maptools.org/
+This is a subset of Shapelib v1.6.0 from http://shapelib.maptools.org/
The source is unmodified. It's subsetted here only to reduce
the amount of size in our tree that it takes and to reduce ongoing
pszDBFFile: The name of the xBase (.dbf) file to access.
pszAccess: The fopen() style access string. At this time only
- "rb" (read-only binary) and "rb+" (read/write binary)
+ "rb" (read-only binary) and "rb+" (read/write binary)
should be used.
</pre>
The DBFOpen() function should be used to establish access to an existing
- xBase format table file. The returned DBFHandle is passed to other
- access functions, and DBFClose() should be invoked to recover resources, and
+ xBase format table file. The returned DBFHandle is passed to other
+ access functions, and DBFClose() should be invoked to recover resources, and
flush changes to disk when complete. The DBFCreate() function should
called to create new xBase files. As a convenience, DBFOpen() can be
called with the name of a .shp or .shx file, and it will figure out the
pszDBFFile: The name of the xBase (.dbf) file to create.
</pre>
-
- The DBFCreate() function creates a new xBase format file with the given
+
+ The DBFCreate() function creates a new xBase format file with the given
name, and returns an access handle that can be used with other DBF functions.
The newly created file will have no fields, and no records. Fields should
be added with DBFAddField() before any records add written.
hDBF: The access handle for the file to be queried, as returned by
DBFOpen(), or DBFCreate().
- iField: The field to be queried. This should be a number between
+ iField: The field to be queried. This should be a number between
0 and n-1, where n is the number fields on the file, as
returned by DBFGetFieldCount().
pszFieldName: If this pointer is not NULL the name of the requested field
- will be written to this location. The pszFieldName buffer
+ will be written to this location. The pszFieldName buffer
should be at least 12 character is size in order to hold
- the longest possible field name of 11 characters plus a
+ the longest possible field name of 11 characters plus a
terminating zero character.
pnWidth: If this pointer is not NULL, the width of the requested field
will be returned in the int pointed to by pnWidth. This is
- the width in characters.
+ the width in characters.
pnDecimals: If this pointer is not NULL, the number of decimal places
precision defined for the field will be returned. This is
<h2>DBFAddField()</h2>
<pre>
-int DBFAddField( DBFHandle hDBF, const char * pszFieldName,
+int DBFAddField( DBFHandle hDBF, const char * pszFieldName,
DBFFieldType eType, int nWidth, int nDecimals );
hDBF: The access handle for the file to be updated, as returned by
<pre>
int DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
-
+
hDBF: The access handle for the file to be queried, as returned by
DBFOpen(), or DBFCreate().
<pre>
double DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
-
+
hDBF: The access handle for the file to be queried, as returned by
DBFOpen(), or DBFCreate().
<pre>
const char *DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
-
+
hDBF: The access handle for the file to be queried, as returned by
DBFOpen(), or DBFCreate().
</pre>
The DBFReadStringAttribute() will read the value of one field and return
- it as a string. This function may be used on any field type (including
+ it as a string. This function may be used on any field type (including
FTInteger and FTDouble) and will return the string representation stored
in the .dbf file. The returned pointer is to an internal buffer
- which is only valid untill the next DBF function call. It's contents may
+ which is only valid until the next DBF function call. It's contents may
be copied with normal string functions such as strcpy(), or strdup(). If
the TRIM_DBF_WHITESPACE macro is defined in shapefil.h (it is by default)
then all leading and trailing space (ASCII 32) characters will be stripped
<pre>
int DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
-
+
hDBF: The access handle for the file to be queried, as returned by
DBFOpen(), or DBFCreate().
This function will return TRUE if the indicated field is NULL valued
otherwise FALSE. Note that NULL fields are represented in the .dbf file
as having all spaces in the field. Reading NULL fields will result in
- a value of 0.0 or an empty string with the other DBFRead*Attribute()
+ a value of 0.0 or an empty string with the other DBFRead*Attribute()
functions.<p>
<!-------------------------------------------------------------------------->
The DBFWriteIntegerAttribute() function is used to write a value to a numeric
field (FTInteger, or FTDouble). If the write succeeds the value TRUE will
-be returned, otherwise FALSE will be returned. If the value is too large to
+be returned, otherwise FALSE will be returned. If the value is too large to
fit in the field, it will be truncated and FALSE returned.<p>
<!-------------------------------------------------------------------------->
The DBFWriteDoubleAttribute() function is used to write a value to a numeric
field (FTInteger, or FTDouble). If the write succeeds the value TRUE will
-be returned, otherwise FALSE will be returned. If the value is too large to
+be returned, otherwise FALSE will be returned. If the value is too large to
fit in the field, it will be truncated and FALSE returned.<p>
<!-------------------------------------------------------------------------->
</pre>
The DBFWriteStringAttribute() function is used to write a value to a string
-field (FString). If the write succeeds the value TRUE willbe returned,
-otherwise FALSE will be returned. If the value is too large to
+field (FString). If the write succeeds the value TRUE willbe returned,
+otherwise FALSE will be returned. If the value is too large to
fit in the field, it will be truncated and FALSE returned.<p>
<!-------------------------------------------------------------------------->
The DBFWriteNULLAttribute() function is used to clear the indicated field
to a NULL value. In the .dbf file this is represented by setting the entire
-field to spaces. If the write succeeds the value TRUE willbe returned,
+field to spaces. If the write succeeds the value TRUE willbe returned,
otherwise FALSE will be returned.<p>
<!-------------------------------------------------------------------------->
hDBF: The access handle for the file.
iField: The field index to query.
-
+
</pre>
This function returns the DBF type code of the indicated field. It will
/******************************************************************************
- * $Id: dbfopen.c,v 1.94 2018-08-16 15:39:07 erouault Exp $
*
* Project: Shapelib
* Purpose: Implementation of .dbf access API documented in dbf_api.html.
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
- * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2012-2019, Even Rouault <even dot rouault at spatialys.com>
*
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see COPYING). This
- * option is discussed in more detail in shapelib.html.
- *
- * --
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- *
- * $Log: dbfopen.c,v $
- * Revision 1.94 2018-08-16 15:39:07 erouault
- * * shpopen.c, dbfopen.c, shptree.c, sbnsearch.c: resyc with GDAL
- * internal shapelib. Mostly to allow building those files as C++
- * without warning. Also add FTDate entry in DBFFieldType
- * (see https://github.com/OSGeo/gdal/pull/308). And some other
- * code cleanups
- *
- * Revision 1.93 2018-08-16 15:24:46 erouault
- * * dbfopen.c: fix a bug where the end of file character was
- * written on top of the first character of the first field name
- * when deleting a field on a .dbf without records.
- * Fixes https://github.com/OSGeo/gdal/issues/863
- *
- * Revision 1.92 2016-12-05 18:44:08 erouault
- * * dbfopen.c, shapefil.h: write DBF end-of-file character 0x1A by default.
- * This behaviour can be controlled with the DBFSetWriteEndOfFileChar()
- * function.
- *
- * Revision 1.91 2016-12-05 12:44:05 erouault
- * * Major overhaul of Makefile build system to use autoconf/automake.
- *
- * * Warning fixes in contrib/
- *
- * Revision 1.90 2016-12-04 15:30:15 erouault
- * * shpopen.c, dbfopen.c, shptree.c, shapefil.h: resync with
- * GDAL Shapefile driver. Mostly cleanups. SHPObject and DBFInfo
- * structures extended with new members. New functions:
- * DBFSetLastModifiedDate, SHPOpenLLEx, SHPRestoreSHX,
- * SHPSetFastModeReadObject
- *
- * * sbnsearch.c: new file to implement original ESRI .sbn spatial
- * index reading. (no write support). New functions:
- * SBNOpenDiskTree, SBNCloseDiskTree, SBNSearchDiskTree,
- * SBNSearchDiskTreeInteger, SBNSearchFreeIds
- *
- * * Makefile, makefile.vc, CMakeLists.txt, shapelib.def: updates
- * with new file and symbols.
- *
- * * commit: helper script to cvs commit
- *
- * Revision 1.89 2011-07-24 05:59:25 fwarmerdam
- * minimize use of CPLError in favor of SAHooks.Error()
- *
- * Revision 1.88 2011-05-13 17:35:17 fwarmerdam
- * added DBFReorderFields() and DBFAlterFields() functions (from Even)
- *
- * Revision 1.87 2011-05-07 22:41:02 fwarmerdam
- * ensure pending record is flushed when adding a native field (GDAL #4073)
- *
- * Revision 1.86 2011-04-17 15:15:29 fwarmerdam
- * Removed unused variable.
- *
- * Revision 1.85 2010-12-06 16:09:34 fwarmerdam
- * fix buffer read overrun fetching code page (bug 2276)
- *
- * Revision 1.84 2009-10-29 19:59:48 fwarmerdam
- * avoid crash on truncated header (gdal #3093)
- *
- * Revision 1.83 2008/11/12 14:28:15 fwarmerdam
- * DBFCreateField() now works on files with records
- *
- * Revision 1.82 2008/11/11 17:47:09 fwarmerdam
- * added DBFDeleteField() function
- *
- * Revision 1.81 2008/01/03 17:48:13 bram
- * in DBFCreate, use default code page LDID/87 (= 0x57, ANSI)
- * instead of LDID/3. This seems to be the same as what ESRI
- * would be doing by default.
- *
- * Revision 1.80 2007/12/30 14:36:39 fwarmerdam
- * avoid syntax issue with last comment.
- *
- * Revision 1.79 2007/12/30 14:35:48 fwarmerdam
- * Avoid char* / unsigned char* warnings.
- *
- * Revision 1.78 2007/12/18 18:28:07 bram
- * - create hook for client specific atof (bugzilla ticket 1615)
- * - check for NULL handle before closing cpCPG file, and close after reading.
- *
- * Revision 1.77 2007/12/15 20:25:21 bram
- * dbfopen.c now reads the Code Page information from the DBF file, and exports
- * this information as a string through the DBFGetCodePage function. This is
- * either the number from the LDID header field ("LDID/<number>") or as the
- * content of an accompanying .CPG file. When creating a DBF file, the code can
- * be set using DBFCreateEx.
- *
- * Revision 1.76 2007/12/12 22:21:32 bram
- * DBFClose: check for NULL psDBF handle before trying to close it.
- *
- * Revision 1.75 2007/12/06 13:58:19 fwarmerdam
- * make sure file offset calculations are done in as SAOffset
- *
- * Revision 1.74 2007/12/06 07:00:25 fwarmerdam
- * dbfopen now using SAHooks for fileio
- *
- * Revision 1.73 2007/09/03 19:48:11 fwarmerdam
- * move DBFReadAttribute() static dDoubleField into dbfinfo
- *
- * Revision 1.72 2007/09/03 19:34:06 fwarmerdam
- * Avoid use of static tuple buffer in DBFReadTuple()
- *
- * Revision 1.71 2006/06/22 14:37:18 fwarmerdam
- * avoid memory leak if dbfopen fread fails
- *
- * Revision 1.70 2006/06/17 17:47:05 fwarmerdam
- * use calloc() for dbfinfo in DBFCreate
- *
- * Revision 1.69 2006/06/17 15:34:32 fwarmerdam
- * disallow creating fields wider than 255
- *
- * Revision 1.68 2006/06/17 15:12:40 fwarmerdam
- * Fixed C++ style comments.
- *
- * Revision 1.67 2006/06/17 00:24:53 fwarmerdam
- * Don't treat non-zero decimals values as high order byte for length
- * for strings. It causes serious corruption for some files.
- * http://bugzilla.remotesensing.org/show_bug.cgi?id=1202
- *
- * Revision 1.66 2006/03/29 18:26:20 fwarmerdam
- * fixed bug with size of pachfieldtype in dbfcloneempty
- *
- * Revision 1.65 2006/02/15 01:14:30 fwarmerdam
- * added DBFAddNativeFieldType
- *
- * Revision 1.64 2006/02/09 00:29:04 fwarmerdam
- * Changed to put spaces into string fields that are NULL as
- * per http://bugzilla.maptools.org/show_bug.cgi?id=316.
- *
- * Revision 1.63 2006/01/25 15:35:43 fwarmerdam
- * check success on DBFFlushRecord
- *
- * Revision 1.62 2006/01/10 16:28:03 fwarmerdam
- * Fixed typo in CPLError.
- *
- * Revision 1.61 2006/01/10 16:26:29 fwarmerdam
- * Push loading record buffer into DBFLoadRecord.
- * Implement CPL error reporting if USE_CPL defined.
- *
- * Revision 1.60 2006/01/05 01:27:27 fwarmerdam
- * added dbf deletion mark/fetch
- *
- * Revision 1.59 2005/03/14 15:20:28 fwarmerdam
- * Fixed last change.
- *
- * Revision 1.58 2005/03/14 15:18:54 fwarmerdam
- * Treat very wide fields with no decimals as double. This is
- * more than 32bit integer fields.
- *
- * Revision 1.57 2005/02/10 20:16:54 fwarmerdam
- * Make the pszStringField buffer for DBFReadAttribute() static char [256]
- * as per bug 306.
- *
- * Revision 1.56 2005/02/10 20:07:56 fwarmerdam
- * Fixed bug 305 in DBFCloneEmpty() - header length problem.
- *
- * Revision 1.55 2004/09/26 20:23:46 fwarmerdam
- * avoid warnings with rcsid and signed/unsigned stuff
- *
- * Revision 1.54 2004/09/15 16:26:10 fwarmerdam
- * Treat all blank numeric fields as null too.
- */
+ * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+ ******************************************************************************/
#include "shapefil.h"
#include <math.h>
+#include <stdbool.h>
+#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "cpl_string.h"
#else
-#if defined(WIN32) || defined(_WIN32)
-# define STRCASECMP(a,b) (stricmp(a,b))
-# else
+#if defined(_MSC_VER)
+#define STRCASECMP(a, b) (_stricmp(a, b))
+#elif defined(WIN32) || defined(_WIN32)
+#define STRCASECMP(a, b) (stricmp(a, b))
+#else
#include <strings.h>
-# define STRCASECMP(a,b) (strcasecmp(a,b))
+#define STRCASECMP(a, b) (strcasecmp(a, b))
#endif
#if defined(_MSC_VER)
-# if _MSC_VER < 1900
-# define snprintf _snprintf
-# endif
+#if _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
#elif defined(WIN32) || defined(_WIN32)
-# ifndef snprintf
-# define snprintf _snprintf
-# endif
+#ifndef snprintf
+#define snprintf _snprintf
+#endif
#endif
#define CPLsprintf sprintf
#define CPLsnprintf snprintf
#endif
-SHP_CVSID("$Id: dbfopen.c,v 1.94 2018-08-16 15:39:07 erouault Exp $")
-
#ifndef FALSE
-# define FALSE 0
-# define TRUE 1
+#define FALSE 0
+#define TRUE 1
#endif
/* File header size */
-#define XBASE_FILEHDR_SZ 32
+#define XBASE_FILEHDR_SZ 32
#define HEADER_RECORD_TERMINATOR 0x0D
/* See http://www.manmrk.net/tutorials/database/xbase/dbf.html */
-#define END_OF_FILE_CHARACTER 0x1A
+#define END_OF_FILE_CHARACTER 0x1A
#ifdef USE_CPL
-CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
+CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused)
+{
+}
#else
#define CPL_IGNORE_RET_VAL_INT(x) x
#endif
#ifdef __cplusplus
-#define STATIC_CAST(type,x) static_cast<type>(x)
-#define REINTERPRET_CAST(type,x) reinterpret_cast<type>(x)
-#define CONST_CAST(type,x) const_cast<type>(x)
+#define STATIC_CAST(type, x) static_cast<type>(x)
+#define REINTERPRET_CAST(type, x) reinterpret_cast<type>(x)
+#define CONST_CAST(type, x) const_cast<type>(x)
#define SHPLIB_NULLPTR nullptr
#else
-#define STATIC_CAST(type,x) ((type)(x))
-#define REINTERPRET_CAST(type,x) ((type)(x))
-#define CONST_CAST(type,x) ((type)(x))
+#define STATIC_CAST(type, x) ((type)(x))
+#define REINTERPRET_CAST(type, x) ((type)(x))
+#define CONST_CAST(type, x) ((type)(x))
#define SHPLIB_NULLPTR NULL
#endif
-/************************************************************************/
-/* SfRealloc() */
-/* */
-/* A realloc cover function that will access a NULL pointer as */
-/* a valid input. */
-/************************************************************************/
-
-static void * SfRealloc( void * pMem, int nNewSize )
-
-{
- if( pMem == SHPLIB_NULLPTR )
- return malloc(nNewSize);
- else
- return realloc(pMem,nNewSize);
-}
-
/************************************************************************/
/* DBFWriteHeader() */
/* */
/************************************************************************/
static void DBFWriteHeader(DBFHandle psDBF)
-
{
- unsigned char abyHeader[XBASE_FILEHDR_SZ] = { 0 };
+ unsigned char abyHeader[XBASE_FILEHDR_SZ] = {0};
- if( !psDBF->bNoHeader )
+ if (!psDBF->bNoHeader)
return;
psDBF->bNoHeader = FALSE;
-/* -------------------------------------------------------------------- */
-/* Initialize the file header information. */
-/* -------------------------------------------------------------------- */
- abyHeader[0] = 0x03; /* memo field? - just copying */
+ /* -------------------------------------------------------------------- */
+ /* Initialize the file header information. */
+ /* -------------------------------------------------------------------- */
+ abyHeader[0] = 0x03; /* memo field? - just copying */
/* write out update date */
abyHeader[1] = STATIC_CAST(unsigned char, psDBF->nUpdateYearSince1900);
abyHeader[29] = STATIC_CAST(unsigned char, psDBF->iLanguageDriver);
-/* -------------------------------------------------------------------- */
-/* Write the initial 32 byte file header, and all the field */
-/* descriptions. */
-/* -------------------------------------------------------------------- */
- psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
- psDBF->sHooks.FWrite( abyHeader, XBASE_FILEHDR_SZ, 1, psDBF->fp );
- psDBF->sHooks.FWrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields,
- psDBF->fp );
-
-/* -------------------------------------------------------------------- */
-/* Write out the newline character if there is room for it. */
-/* -------------------------------------------------------------------- */
- if( psDBF->nHeaderLength > XBASE_FLDHDR_SZ*psDBF->nFields +
- XBASE_FLDHDR_SZ )
+ /* -------------------------------------------------------------------- */
+ /* Write the initial 32 byte file header, and all the field */
+ /* descriptions. */
+ /* -------------------------------------------------------------------- */
+ psDBF->sHooks.FSeek(psDBF->fp, 0, 0);
+ psDBF->sHooks.FWrite(abyHeader, XBASE_FILEHDR_SZ, 1, psDBF->fp);
+ psDBF->sHooks.FWrite(psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields,
+ psDBF->fp);
+
+ /* -------------------------------------------------------------------- */
+ /* Write out the newline character if there is room for it. */
+ /* -------------------------------------------------------------------- */
+ if (psDBF->nHeaderLength >
+ XBASE_FLDHDR_SZ * psDBF->nFields + XBASE_FLDHDR_SZ)
{
- char cNewline;
-
- cNewline = HEADER_RECORD_TERMINATOR;
- psDBF->sHooks.FWrite( &cNewline, 1, 1, psDBF->fp );
+ char cNewline = HEADER_RECORD_TERMINATOR;
+ psDBF->sHooks.FWrite(&cNewline, 1, 1, psDBF->fp);
}
-/* -------------------------------------------------------------------- */
-/* If the file is new, add a EOF character. */
-/* -------------------------------------------------------------------- */
- if( psDBF->nRecords == 0 && psDBF->bWriteEndOfFileChar )
+ /* -------------------------------------------------------------------- */
+ /* If the file is new, add a EOF character. */
+ /* -------------------------------------------------------------------- */
+ if (psDBF->nRecords == 0 && psDBF->bWriteEndOfFileChar)
{
char ch = END_OF_FILE_CHARACTER;
- psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+ psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
}
}
/* Write out the current record if there is one. */
/************************************************************************/
-static int DBFFlushRecord( DBFHandle psDBF )
-
+static bool DBFFlushRecord(DBFHandle psDBF)
{
- SAOffset nRecordOffset;
-
- if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
+ if (psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1)
{
- psDBF->bCurrentRecordModified = FALSE;
-
- nRecordOffset =
- psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nCurrentRecord)
- + psDBF->nHeaderLength;
+ psDBF->bCurrentRecordModified = FALSE;
+
+ const SAOffset nRecordOffset =
+ psDBF->nRecordLength *
+ STATIC_CAST(SAOffset, psDBF->nCurrentRecord) +
+ psDBF->nHeaderLength;
+
+ /* -------------------------------------------------------------------- */
+ /* Guard FSeek with check for whether we're already at position; */
+ /* no-op FSeeks defeat network filesystems' write buffering. */
+ /* -------------------------------------------------------------------- */
+ if (psDBF->bRequireNextWriteSeek ||
+ psDBF->sHooks.FTell(psDBF->fp) != nRecordOffset)
+ {
+ if (psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0) != 0)
+ {
+ char szMessage[128];
+ snprintf(
+ szMessage, sizeof(szMessage),
+ "Failure seeking to position before writing DBF record %d.",
+ psDBF->nCurrentRecord);
+ psDBF->sHooks.Error(szMessage);
+ return false;
+ }
+ }
- if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 ) != 0
- || psDBF->sHooks.FWrite( psDBF->pszCurrentRecord,
- psDBF->nRecordLength,
- 1, psDBF->fp ) != 1 )
+ if (psDBF->sHooks.FWrite(psDBF->pszCurrentRecord, psDBF->nRecordLength,
+ 1, psDBF->fp) != 1)
{
char szMessage[128];
- snprintf( szMessage, sizeof(szMessage), "Failure writing DBF record %d.",
- psDBF->nCurrentRecord );
- psDBF->sHooks.Error( szMessage );
- return FALSE;
+ snprintf(szMessage, sizeof(szMessage),
+ "Failure writing DBF record %d.", psDBF->nCurrentRecord);
+ psDBF->sHooks.Error(szMessage);
+ return false;
}
- if( psDBF->nCurrentRecord == psDBF->nRecords - 1 )
+ /* -------------------------------------------------------------------- */
+ /* If next op is also a write, allow possible skipping of FSeek. */
+ /* -------------------------------------------------------------------- */
+ psDBF->bRequireNextWriteSeek = FALSE;
+
+ if (psDBF->nCurrentRecord == psDBF->nRecords - 1)
{
- if( psDBF->bWriteEndOfFileChar )
+ if (psDBF->bWriteEndOfFileChar)
{
char ch = END_OF_FILE_CHARACTER;
- psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+ psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
}
}
}
- return TRUE;
+ return true;
}
/************************************************************************/
/* DBFLoadRecord() */
/************************************************************************/
-static int DBFLoadRecord( DBFHandle psDBF, int iRecord )
-
+static bool DBFLoadRecord(DBFHandle psDBF, int iRecord)
{
- if( psDBF->nCurrentRecord != iRecord )
+ if (psDBF->nCurrentRecord != iRecord)
{
- SAOffset nRecordOffset;
+ if (!DBFFlushRecord(psDBF))
+ return false;
- if( !DBFFlushRecord( psDBF ) )
- return FALSE;
-
- nRecordOffset =
- psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+ const SAOffset nRecordOffset =
+ psDBF->nRecordLength * STATIC_CAST(SAOffset, iRecord) +
+ psDBF->nHeaderLength;
- if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, SEEK_SET ) != 0 )
+ if (psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, SEEK_SET) != 0)
{
char szMessage[128];
- snprintf( szMessage, sizeof(szMessage), "fseek(%ld) failed on DBF file.",
- STATIC_CAST(long, nRecordOffset) );
- psDBF->sHooks.Error( szMessage );
- return FALSE;
+ snprintf(szMessage, sizeof(szMessage),
+ "fseek(%ld) failed on DBF file.",
+ STATIC_CAST(long, nRecordOffset));
+ psDBF->sHooks.Error(szMessage);
+ return false;
}
- if( psDBF->sHooks.FRead( psDBF->pszCurrentRecord,
- psDBF->nRecordLength, 1, psDBF->fp ) != 1 )
+ if (psDBF->sHooks.FRead(psDBF->pszCurrentRecord, psDBF->nRecordLength,
+ 1, psDBF->fp) != 1)
{
char szMessage[128];
- snprintf( szMessage, sizeof(szMessage), "fread(%d) failed on DBF file.",
- psDBF->nRecordLength );
- psDBF->sHooks.Error( szMessage );
- return FALSE;
+ snprintf(szMessage, sizeof(szMessage),
+ "fread(%d) failed on DBF file.", psDBF->nRecordLength);
+ psDBF->sHooks.Error(szMessage);
+ return false;
}
- psDBF->nCurrentRecord = iRecord;
+ psDBF->nCurrentRecord = iRecord;
+ /* -------------------------------------------------------------------- */
+ /* Require a seek for next write in case of mixed R/W operations. */
+ /* -------------------------------------------------------------------- */
+ psDBF->bRequireNextWriteSeek = TRUE;
}
- return TRUE;
+ return true;
}
/************************************************************************/
/* DBFUpdateHeader() */
/************************************************************************/
-void SHPAPI_CALL
-DBFUpdateHeader( DBFHandle psDBF )
-
+void SHPAPI_CALL DBFUpdateHeader(DBFHandle psDBF)
{
- unsigned char abyFileHeader[XBASE_FILEHDR_SZ];
-
- if( psDBF->bNoHeader )
- DBFWriteHeader( psDBF );
+ if (psDBF->bNoHeader)
+ DBFWriteHeader(psDBF);
- if( !DBFFlushRecord( psDBF ) )
+ if (!DBFFlushRecord(psDBF))
return;
- psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
- psDBF->sHooks.FRead( abyFileHeader, sizeof(abyFileHeader), 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, 0, 0);
+
+ unsigned char abyFileHeader[XBASE_FILEHDR_SZ] = {0};
+ psDBF->sHooks.FRead(abyFileHeader, 1, sizeof(abyFileHeader), psDBF->fp);
abyFileHeader[1] = STATIC_CAST(unsigned char, psDBF->nUpdateYearSince1900);
abyFileHeader[2] = STATIC_CAST(unsigned char, psDBF->nUpdateMonth);
abyFileHeader[3] = STATIC_CAST(unsigned char, psDBF->nUpdateDay);
abyFileHeader[4] = STATIC_CAST(unsigned char, psDBF->nRecords & 0xFF);
- abyFileHeader[5] = STATIC_CAST(unsigned char, (psDBF->nRecords>>8) & 0xFF);
- abyFileHeader[6] = STATIC_CAST(unsigned char, (psDBF->nRecords>>16) & 0xFF);
- abyFileHeader[7] = STATIC_CAST(unsigned char, (psDBF->nRecords>>24) & 0xFF);
+ abyFileHeader[5] =
+ STATIC_CAST(unsigned char, (psDBF->nRecords >> 8) & 0xFF);
+ abyFileHeader[6] =
+ STATIC_CAST(unsigned char, (psDBF->nRecords >> 16) & 0xFF);
+ abyFileHeader[7] =
+ STATIC_CAST(unsigned char, (psDBF->nRecords >> 24) & 0xFF);
- psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
- psDBF->sHooks.FWrite( abyFileHeader, sizeof(abyFileHeader), 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, 0, 0);
+ psDBF->sHooks.FWrite(abyFileHeader, sizeof(abyFileHeader), 1, psDBF->fp);
- psDBF->sHooks.FFlush( psDBF->fp );
+ psDBF->sHooks.FFlush(psDBF->fp);
}
/************************************************************************/
/* DBFSetLastModifiedDate() */
/************************************************************************/
-void SHPAPI_CALL
-DBFSetLastModifiedDate( DBFHandle psDBF, int nYYSince1900, int nMM, int nDD )
+void SHPAPI_CALL DBFSetLastModifiedDate(DBFHandle psDBF, int nYYSince1900,
+ int nMM, int nDD)
{
psDBF->nUpdateYearSince1900 = nYYSince1900;
psDBF->nUpdateMonth = nMM;
/* Open a .dbf file. */
/************************************************************************/
-DBFHandle SHPAPI_CALL
-DBFOpen( const char * pszFilename, const char * pszAccess )
+DBFHandle SHPAPI_CALL DBFOpen(const char *pszFilename, const char *pszAccess)
{
SAHooks sHooks;
- SASetupDefaultHooks( &sHooks );
+ SASetupDefaultHooks(&sHooks);
- return DBFOpenLL( pszFilename, pszAccess, &sHooks );
+ return DBFOpenLL(pszFilename, pszAccess, &sHooks);
}
/************************************************************************/
/* DBFGetLenWithoutExtension() */
/************************************************************************/
-static int DBFGetLenWithoutExtension(const char* pszBasename)
+static int DBFGetLenWithoutExtension(const char *pszBasename)
{
- int i;
- int nLen = STATIC_CAST(int, strlen(pszBasename));
- for( i = nLen-1;
- i > 0 && pszBasename[i] != '/' && pszBasename[i] != '\\';
- i-- )
+ const int nLen = STATIC_CAST(int, strlen(pszBasename));
+ for (int i = nLen - 1;
+ i > 0 && pszBasename[i] != '/' && pszBasename[i] != '\\'; i--)
{
- if( pszBasename[i] == '.' )
+ if (pszBasename[i] == '.')
{
return i;
}
/* Open a .dbf file. */
/************************************************************************/
-DBFHandle SHPAPI_CALL
-DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
-
+DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszFilename, const char *pszAccess,
+ const SAHooks *psHooks)
{
- DBFHandle psDBF;
- SAFile pfCPG;
- unsigned char *pabyBuf;
- int nFields, nHeadLen, iField;
- char *pszFullname;
- int nBufSize = 500;
- int nLenWithoutExtension;
-
-/* -------------------------------------------------------------------- */
-/* We only allow the access strings "rb" and "r+". */
-/* -------------------------------------------------------------------- */
- if( strcmp(pszAccess,"r") != 0 && strcmp(pszAccess,"r+") != 0
- && strcmp(pszAccess,"rb") != 0 && strcmp(pszAccess,"rb+") != 0
- && strcmp(pszAccess,"r+b") != 0 )
+ /* -------------------------------------------------------------------- */
+ /* We only allow the access strings "rb" and "r+". */
+ /* -------------------------------------------------------------------- */
+ if (strcmp(pszAccess, "r") != 0 && strcmp(pszAccess, "r+") != 0 &&
+ strcmp(pszAccess, "rb") != 0 && strcmp(pszAccess, "rb+") != 0 &&
+ strcmp(pszAccess, "r+b") != 0)
return SHPLIB_NULLPTR;
- if( strcmp(pszAccess,"r") == 0 )
+ if (strcmp(pszAccess, "r") == 0)
pszAccess = "rb";
- if( strcmp(pszAccess,"r+") == 0 )
+ if (strcmp(pszAccess, "r+") == 0)
pszAccess = "rb+";
-/* -------------------------------------------------------------------- */
-/* Compute the base (layer) name. If there is any extension */
-/* on the passed in filename we will strip it off. */
-/* -------------------------------------------------------------------- */
- nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
- pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+ /* -------------------------------------------------------------------- */
+ /* Compute the base (layer) name. If there is any extension */
+ /* on the passed in filename we will strip it off. */
+ /* -------------------------------------------------------------------- */
+ const int nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
+ char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
memcpy(pszFullname, pszFilename, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5);
- psDBF = STATIC_CAST(DBFHandle, calloc( 1, sizeof(DBFInfo) ));
- psDBF->fp = psHooks->FOpen( pszFullname, pszAccess );
- memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
+ DBFHandle psDBF = STATIC_CAST(DBFHandle, calloc(1, sizeof(DBFInfo)));
+ psDBF->fp = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData);
+ memcpy(&(psDBF->sHooks), psHooks, sizeof(SAHooks));
- if( psDBF->fp == SHPLIB_NULLPTR )
+ if (psDBF->fp == SHPLIB_NULLPTR)
{
memcpy(pszFullname + nLenWithoutExtension, ".DBF", 5);
- psDBF->fp = psDBF->sHooks.FOpen(pszFullname, pszAccess );
+ psDBF->fp =
+ psDBF->sHooks.FOpen(pszFullname, pszAccess, psHooks->pvUserData);
}
memcpy(pszFullname + nLenWithoutExtension, ".cpg", 5);
- pfCPG = psHooks->FOpen( pszFullname, "r" );
- if( pfCPG == SHPLIB_NULLPTR )
+ SAFile pfCPG = psHooks->FOpen(pszFullname, "r", psHooks->pvUserData);
+ if (pfCPG == SHPLIB_NULLPTR)
{
memcpy(pszFullname + nLenWithoutExtension, ".CPG", 5);
- pfCPG = psHooks->FOpen( pszFullname, "r" );
+ pfCPG = psHooks->FOpen(pszFullname, "r", psHooks->pvUserData);
}
- free( pszFullname );
+ free(pszFullname);
- if( psDBF->fp == SHPLIB_NULLPTR )
+ if (psDBF->fp == SHPLIB_NULLPTR)
{
- free( psDBF );
- if( pfCPG ) psHooks->FClose( pfCPG );
+ free(psDBF);
+ if (pfCPG)
+ psHooks->FClose(pfCPG);
return SHPLIB_NULLPTR;
}
psDBF->nCurrentRecord = -1;
psDBF->bCurrentRecordModified = FALSE;
-/* -------------------------------------------------------------------- */
-/* Read Table Header info */
-/* -------------------------------------------------------------------- */
- pabyBuf = STATIC_CAST(unsigned char *, malloc(nBufSize));
- if( psDBF->sHooks.FRead( pabyBuf, XBASE_FILEHDR_SZ, 1, psDBF->fp ) != 1 )
+ /* -------------------------------------------------------------------- */
+ /* Read Table Header info */
+ /* -------------------------------------------------------------------- */
+ const int nBufSize = 500;
+ unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(nBufSize));
+ if (psDBF->sHooks.FRead(pabyBuf, XBASE_FILEHDR_SZ, 1, psDBF->fp) != 1)
{
- psDBF->sHooks.FClose( psDBF->fp );
- if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
- free( pabyBuf );
- free( psDBF );
+ psDBF->sHooks.FClose(psDBF->fp);
+ if (pfCPG)
+ psDBF->sHooks.FClose(pfCPG);
+ free(pabyBuf);
+ free(psDBF);
return SHPLIB_NULLPTR;
}
DBFSetLastModifiedDate(psDBF, pabyBuf[1], pabyBuf[2], pabyBuf[3]);
- psDBF->nRecords =
- pabyBuf[4]|(pabyBuf[5]<<8)|(pabyBuf[6]<<16)|((pabyBuf[7]&0x7f)<<24);
+ psDBF->nRecords = pabyBuf[4] | (pabyBuf[5] << 8) | (pabyBuf[6] << 16) |
+ ((pabyBuf[7] & 0x7f) << 24);
- psDBF->nHeaderLength = nHeadLen = pabyBuf[8]|(pabyBuf[9]<<8);
- psDBF->nRecordLength = pabyBuf[10]|(pabyBuf[11]<<8);
+ const int nHeadLen = pabyBuf[8] | (pabyBuf[9] << 8);
+ psDBF->nHeaderLength = nHeadLen;
+ psDBF->nRecordLength = pabyBuf[10] | (pabyBuf[11] << 8);
psDBF->iLanguageDriver = pabyBuf[29];
if (psDBF->nRecordLength == 0 || nHeadLen < XBASE_FILEHDR_SZ)
{
- psDBF->sHooks.FClose( psDBF->fp );
- if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
- free( pabyBuf );
- free( psDBF );
+ psDBF->sHooks.FClose(psDBF->fp);
+ if (pfCPG)
+ psDBF->sHooks.FClose(pfCPG);
+ free(pabyBuf);
+ free(psDBF);
return SHPLIB_NULLPTR;
}
- psDBF->nFields = nFields = (nHeadLen - XBASE_FILEHDR_SZ) / XBASE_FLDHDR_SZ;
+ const int nFields = (nHeadLen - XBASE_FILEHDR_SZ) / XBASE_FLDHDR_SZ;
+ psDBF->nFields = nFields;
/* coverity[tainted_data] */
psDBF->pszCurrentRecord = STATIC_CAST(char *, malloc(psDBF->nRecordLength));
-/* -------------------------------------------------------------------- */
-/* Figure out the code page from the LDID and CPG */
-/* -------------------------------------------------------------------- */
-
+ /* -------------------------------------------------------------------- */
+ /* Figure out the code page from the LDID and CPG */
+ /* -------------------------------------------------------------------- */
psDBF->pszCodePage = SHPLIB_NULLPTR;
- if( pfCPG )
+ if (pfCPG)
{
- size_t n;
- memset( pabyBuf, 0, nBufSize);
- psDBF->sHooks.FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
- n = strcspn( REINTERPRET_CAST(char *, pabyBuf), "\n\r" );
- if( n > 0 )
+ memset(pabyBuf, 0, nBufSize);
+ psDBF->sHooks.FRead(pabyBuf, 1, nBufSize - 1, pfCPG);
+ const size_t n = strcspn(REINTERPRET_CAST(char *, pabyBuf), "\n\r");
+ if (n > 0)
{
pabyBuf[n] = '\0';
psDBF->pszCodePage = STATIC_CAST(char *, malloc(n + 1));
- memcpy( psDBF->pszCodePage, pabyBuf, n + 1 );
+ memcpy(psDBF->pszCodePage, pabyBuf, n + 1);
}
- psDBF->sHooks.FClose( pfCPG );
+ psDBF->sHooks.FClose(pfCPG);
}
- if( psDBF->pszCodePage == SHPLIB_NULLPTR && pabyBuf[29] != 0 )
+ if (psDBF->pszCodePage == SHPLIB_NULLPTR && pabyBuf[29] != 0)
{
- snprintf( REINTERPRET_CAST(char *, pabyBuf), nBufSize, "LDID/%d", psDBF->iLanguageDriver );
- psDBF->pszCodePage = STATIC_CAST(char *, malloc(strlen(REINTERPRET_CAST(char*, pabyBuf)) + 1));
- strcpy( psDBF->pszCodePage, REINTERPRET_CAST(char *, pabyBuf) );
+ snprintf(REINTERPRET_CAST(char *, pabyBuf), nBufSize, "LDID/%d",
+ psDBF->iLanguageDriver);
+ psDBF->pszCodePage = STATIC_CAST(
+ char *, malloc(strlen(REINTERPRET_CAST(char *, pabyBuf)) + 1));
+ strcpy(psDBF->pszCodePage, REINTERPRET_CAST(char *, pabyBuf));
}
-/* -------------------------------------------------------------------- */
-/* Read in Field Definitions */
-/* -------------------------------------------------------------------- */
-
- pabyBuf = STATIC_CAST(unsigned char *, SfRealloc(pabyBuf,nHeadLen));
+ /* -------------------------------------------------------------------- */
+ /* Read in Field Definitions */
+ /* -------------------------------------------------------------------- */
+ pabyBuf = STATIC_CAST(unsigned char *, realloc(pabyBuf, nHeadLen));
psDBF->pszHeader = REINTERPRET_CAST(char *, pabyBuf);
- psDBF->sHooks.FSeek( psDBF->fp, XBASE_FILEHDR_SZ, 0 );
- if( psDBF->sHooks.FRead( pabyBuf, nHeadLen-XBASE_FILEHDR_SZ, 1,
- psDBF->fp ) != 1 )
+ psDBF->sHooks.FSeek(psDBF->fp, XBASE_FILEHDR_SZ, 0);
+ if (psDBF->sHooks.FRead(pabyBuf, nHeadLen - XBASE_FILEHDR_SZ, 1,
+ psDBF->fp) != 1)
{
- psDBF->sHooks.FClose( psDBF->fp );
- free( pabyBuf );
- free( psDBF->pszCurrentRecord );
- free( psDBF->pszCodePage );
- free( psDBF );
+ psDBF->sHooks.FClose(psDBF->fp);
+ free(pabyBuf);
+ free(psDBF->pszCurrentRecord);
+ free(psDBF->pszCodePage);
+ free(psDBF);
return SHPLIB_NULLPTR;
}
psDBF->panFieldDecimals = STATIC_CAST(int *, malloc(sizeof(int) * nFields));
psDBF->pachFieldType = STATIC_CAST(char *, malloc(sizeof(char) * nFields));
- for( iField = 0; iField < nFields; iField++ )
+ for (int iField = 0; iField < nFields; iField++)
{
- unsigned char *pabyFInfo;
-
- pabyFInfo = pabyBuf+iField*XBASE_FLDHDR_SZ;
- if( pabyFInfo[0] == HEADER_RECORD_TERMINATOR )
+ unsigned char *pabyFInfo = pabyBuf + iField * XBASE_FLDHDR_SZ;
+ if (pabyFInfo[0] == HEADER_RECORD_TERMINATOR)
{
psDBF->nFields = iField;
break;
}
- if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
- {
- psDBF->panFieldSize[iField] = pabyFInfo[16];
- psDBF->panFieldDecimals[iField] = pabyFInfo[17];
- }
- else
- {
- psDBF->panFieldSize[iField] = pabyFInfo[16];
- psDBF->panFieldDecimals[iField] = 0;
-
-/*
-** The following seemed to be used sometimes to handle files with long
-** string fields, but in other cases (such as bug 1202) the decimals field
-** just seems to indicate some sort of preferred formatting, not very
-** wide fields. So I have disabled this code. FrankW.
- psDBF->panFieldSize[iField] = pabyFInfo[16] + pabyFInfo[17]*256;
- psDBF->panFieldDecimals[iField] = 0;
-*/
- }
-
- psDBF->pachFieldType[iField] = STATIC_CAST(char, pabyFInfo[11]);
- if( iField == 0 )
- psDBF->panFieldOffset[iField] = 1;
- else
- psDBF->panFieldOffset[iField] =
- psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
+ if (pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F')
+ {
+ psDBF->panFieldSize[iField] = pabyFInfo[16];
+ psDBF->panFieldDecimals[iField] = pabyFInfo[17];
+ }
+ else
+ {
+ psDBF->panFieldSize[iField] = pabyFInfo[16];
+ psDBF->panFieldDecimals[iField] = 0;
+
+ /*
+ ** The following seemed to be used sometimes to handle files with
+ long
+ ** string fields, but in other cases (such as bug 1202) the decimals
+ field
+ ** just seems to indicate some sort of preferred formatting, not
+ very
+ ** wide fields. So I have disabled this code. FrankW.
+ psDBF->panFieldSize[iField] = pabyFInfo[16] +
+ pabyFInfo[17]*256; psDBF->panFieldDecimals[iField] = 0;
+ */
+ }
+
+ psDBF->pachFieldType[iField] = STATIC_CAST(char, pabyFInfo[11]);
+ if (iField == 0)
+ psDBF->panFieldOffset[iField] = 1;
+ else
+ psDBF->panFieldOffset[iField] = psDBF->panFieldOffset[iField - 1] +
+ psDBF->panFieldSize[iField - 1];
}
/* Check that the total width of fields does not exceed the record width */
- if( psDBF->nFields > 0 &&
- psDBF->panFieldOffset[psDBF->nFields-1] +
- psDBF->panFieldSize[psDBF->nFields-1] > psDBF->nRecordLength )
+ if (psDBF->nFields > 0 && psDBF->panFieldOffset[psDBF->nFields - 1] +
+ psDBF->panFieldSize[psDBF->nFields - 1] >
+ psDBF->nRecordLength)
{
- DBFClose( psDBF );
+ DBFClose(psDBF);
return SHPLIB_NULLPTR;
}
- DBFSetWriteEndOfFileChar( psDBF, TRUE );
+ DBFSetWriteEndOfFileChar(psDBF, TRUE);
+
+ psDBF->bRequireNextWriteSeek = TRUE;
- return( psDBF );
+ return (psDBF);
}
/************************************************************************/
/* DBFClose() */
/************************************************************************/
-void SHPAPI_CALL
-DBFClose(DBFHandle psDBF)
+void SHPAPI_CALL DBFClose(DBFHandle psDBF)
{
- if( psDBF == SHPLIB_NULLPTR )
+ if (psDBF == SHPLIB_NULLPTR)
return;
-/* -------------------------------------------------------------------- */
-/* Write out header if not already written. */
-/* -------------------------------------------------------------------- */
- if( psDBF->bNoHeader )
- DBFWriteHeader( psDBF );
+ /* -------------------------------------------------------------------- */
+ /* Write out header if not already written. */
+ /* -------------------------------------------------------------------- */
+ if (psDBF->bNoHeader)
+ DBFWriteHeader(psDBF);
- CPL_IGNORE_RET_VAL_INT(DBFFlushRecord( psDBF ));
+ CPL_IGNORE_RET_VAL_INT(DBFFlushRecord(psDBF));
-/* -------------------------------------------------------------------- */
-/* Update last access date, and number of records if we have */
-/* write access. */
-/* -------------------------------------------------------------------- */
- if( psDBF->bUpdated )
- DBFUpdateHeader( psDBF );
+ /* -------------------------------------------------------------------- */
+ /* Update last access date, and number of records if we have */
+ /* write access. */
+ /* -------------------------------------------------------------------- */
+ if (psDBF->bUpdated)
+ DBFUpdateHeader(psDBF);
-/* -------------------------------------------------------------------- */
-/* Close, and free resources. */
-/* -------------------------------------------------------------------- */
- psDBF->sHooks.FClose( psDBF->fp );
+ /* -------------------------------------------------------------------- */
+ /* Close, and free resources. */
+ /* -------------------------------------------------------------------- */
+ psDBF->sHooks.FClose(psDBF->fp);
- if( psDBF->panFieldOffset != SHPLIB_NULLPTR )
+ if (psDBF->panFieldOffset != SHPLIB_NULLPTR)
{
- free( psDBF->panFieldOffset );
- free( psDBF->panFieldSize );
- free( psDBF->panFieldDecimals );
- free( psDBF->pachFieldType );
+ free(psDBF->panFieldOffset);
+ free(psDBF->panFieldSize);
+ free(psDBF->panFieldDecimals);
+ free(psDBF->pachFieldType);
}
- if( psDBF->pszWorkField != SHPLIB_NULLPTR )
- free( psDBF->pszWorkField );
+ if (psDBF->pszWorkField != SHPLIB_NULLPTR)
+ free(psDBF->pszWorkField);
- free( psDBF->pszHeader );
- free( psDBF->pszCurrentRecord );
- free( psDBF->pszCodePage );
+ free(psDBF->pszHeader);
+ free(psDBF->pszCurrentRecord);
+ free(psDBF->pszCodePage);
- free( psDBF );
+ free(psDBF);
}
/************************************************************************/
/* Create a new .dbf file with default code page LDID/87 (0x57) */
/************************************************************************/
-DBFHandle SHPAPI_CALL
-DBFCreate( const char * pszFilename )
-
+DBFHandle SHPAPI_CALL DBFCreate(const char *pszFilename)
{
- return DBFCreateEx( pszFilename, "LDID/87" ); // 0x57
+ return DBFCreateEx(pszFilename, "LDID/87"); // 0x57
}
/************************************************************************/
/* Create a new .dbf file. */
/************************************************************************/
-DBFHandle SHPAPI_CALL
-DBFCreateEx( const char * pszFilename, const char* pszCodePage )
-
+DBFHandle SHPAPI_CALL DBFCreateEx(const char *pszFilename,
+ const char *pszCodePage)
{
SAHooks sHooks;
- SASetupDefaultHooks( &sHooks );
+ SASetupDefaultHooks(&sHooks);
- return DBFCreateLL( pszFilename, pszCodePage , &sHooks );
+ return DBFCreateLL(pszFilename, pszCodePage, &sHooks);
}
/************************************************************************/
/* Create a new .dbf file. */
/************************************************************************/
-DBFHandle SHPAPI_CALL
-DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHooks )
-
+DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszFilename,
+ const char *pszCodePage,
+ const SAHooks *psHooks)
{
- DBFHandle psDBF;
- SAFile fp;
- char *pszFullname;
- int ldid = -1;
- char chZero = '\0';
- int nLenWithoutExtension;
-
-/* -------------------------------------------------------------------- */
-/* Compute the base (layer) name. If there is any extension */
-/* on the passed in filename we will strip it off. */
-/* -------------------------------------------------------------------- */
- nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
- pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+ /* -------------------------------------------------------------------- */
+ /* Compute the base (layer) name. If there is any extension */
+ /* on the passed in filename we will strip it off. */
+ /* -------------------------------------------------------------------- */
+ const int nLenWithoutExtension = DBFGetLenWithoutExtension(pszFilename);
+ char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
memcpy(pszFullname, pszFilename, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".dbf", 5);
-/* -------------------------------------------------------------------- */
-/* Create the file. */
-/* -------------------------------------------------------------------- */
- fp = psHooks->FOpen( pszFullname, "wb" );
- if( fp == SHPLIB_NULLPTR )
- {
- free( pszFullname );
- return SHPLIB_NULLPTR;
- }
-
- psHooks->FWrite( &chZero, 1, 1, fp );
- psHooks->FClose( fp );
-
- fp = psHooks->FOpen( pszFullname, "rb+" );
- if( fp == SHPLIB_NULLPTR )
+ /* -------------------------------------------------------------------- */
+ /* Create the file. */
+ /* -------------------------------------------------------------------- */
+ SAFile fp = psHooks->FOpen(pszFullname, "wb+", psHooks->pvUserData);
+ if (fp == SHPLIB_NULLPTR)
{
- free( pszFullname );
+ free(pszFullname);
return SHPLIB_NULLPTR;
}
memcpy(pszFullname + nLenWithoutExtension, ".cpg", 5);
- if( pszCodePage != SHPLIB_NULLPTR )
+ int ldid = -1;
+ if (pszCodePage != SHPLIB_NULLPTR)
{
- if( strncmp( pszCodePage, "LDID/", 5 ) == 0 )
+ if (strncmp(pszCodePage, "LDID/", 5) == 0)
{
- ldid = atoi( pszCodePage + 5 );
- if( ldid > 255 )
- ldid = -1; // don't use 0 to indicate out of range as LDID/0 is a valid one
+ ldid = atoi(pszCodePage + 5);
+ if (ldid > 255)
+ ldid = -1; // don't use 0 to indicate out of range as LDID/0 is
+ // a valid one
}
- if( ldid < 0 )
+ if (ldid < 0)
{
- SAFile fpCPG = psHooks->FOpen( pszFullname, "w" );
- psHooks->FWrite( CONST_CAST(void*, STATIC_CAST(const void*, pszCodePage)), strlen(pszCodePage), 1, fpCPG );
- psHooks->FClose( fpCPG );
+ SAFile fpCPG =
+ psHooks->FOpen(pszFullname, "w", psHooks->pvUserData);
+ psHooks->FWrite(
+ CONST_CAST(void *, STATIC_CAST(const void *, pszCodePage)),
+ strlen(pszCodePage), 1, fpCPG);
+ psHooks->FClose(fpCPG);
}
}
- if( pszCodePage == SHPLIB_NULLPTR || ldid >= 0 )
+ if (pszCodePage == SHPLIB_NULLPTR || ldid >= 0)
{
- psHooks->Remove( pszFullname );
+ psHooks->Remove(pszFullname, psHooks->pvUserData);
}
- free( pszFullname );
+ free(pszFullname);
-/* -------------------------------------------------------------------- */
-/* Create the info structure. */
-/* -------------------------------------------------------------------- */
- psDBF = STATIC_CAST(DBFHandle, calloc(1,sizeof(DBFInfo)));
+ /* -------------------------------------------------------------------- */
+ /* Create the info structure. */
+ /* -------------------------------------------------------------------- */
+ DBFHandle psDBF = STATIC_CAST(DBFHandle, calloc(1, sizeof(DBFInfo)));
- memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
+ memcpy(&(psDBF->sHooks), psHooks, sizeof(SAHooks));
psDBF->fp = fp;
psDBF->nRecords = 0;
psDBF->nFields = 0;
psDBF->nRecordLength = 1;
- psDBF->nHeaderLength = XBASE_FILEHDR_SZ + 1; /* + 1 for HEADER_RECORD_TERMINATOR */
+ psDBF->nHeaderLength =
+ XBASE_FILEHDR_SZ + 1; /* + 1 for HEADER_RECORD_TERMINATOR */
psDBF->panFieldOffset = SHPLIB_NULLPTR;
psDBF->panFieldSize = SHPLIB_NULLPTR;
psDBF->iLanguageDriver = ldid > 0 ? ldid : 0;
psDBF->pszCodePage = SHPLIB_NULLPTR;
- if( pszCodePage )
+ if (pszCodePage)
{
- psDBF->pszCodePage = STATIC_CAST(char *, malloc( strlen(pszCodePage) + 1 ));
- strcpy( psDBF->pszCodePage, pszCodePage );
+ psDBF->pszCodePage =
+ STATIC_CAST(char *, malloc(strlen(pszCodePage) + 1));
+ strcpy(psDBF->pszCodePage, pszCodePage);
}
DBFSetLastModifiedDate(psDBF, 95, 7, 26); /* dummy date */
DBFSetWriteEndOfFileChar(psDBF, TRUE);
- return( psDBF );
+ psDBF->bRequireNextWriteSeek = TRUE;
+
+ return (psDBF);
}
/************************************************************************/
/* Add a field to a newly created .dbf or to an existing one */
/************************************************************************/
-int SHPAPI_CALL
-DBFAddField(DBFHandle psDBF, const char * pszFieldName,
- DBFFieldType eType, int nWidth, int nDecimals )
-
+int SHPAPI_CALL DBFAddField(DBFHandle psDBF, const char *pszFieldName,
+ DBFFieldType eType, int nWidth, int nDecimals)
{
- char chNativeType = 'C';
+ char chNativeType;
- if( eType == FTLogical )
+ if (eType == FTLogical)
chNativeType = 'L';
- else if( eType == FTDate )
- chNativeType = 'D';
- else if( eType == FTString )
+ else if (eType == FTDate)
+ chNativeType = 'D';
+ else if (eType == FTString)
chNativeType = 'C';
else
chNativeType = 'N';
- return DBFAddNativeFieldType( psDBF, pszFieldName, chNativeType,
- nWidth, nDecimals );
+ return DBFAddNativeFieldType(psDBF, pszFieldName, chNativeType, nWidth,
+ nDecimals);
}
/************************************************************************/
{
switch (chType)
{
- case 'N':
- case 'F':
- return '*';
- case 'D':
- return '0';
- case 'L':
- return '?';
- default:
- return ' ';
+ case 'N':
+ case 'F':
+ return '*';
+ case 'D':
+ return '0';
+ case 'L':
+ return '?';
+ default:
+ return ' ';
}
}
/* are written. */
/************************************************************************/
-int SHPAPI_CALL
-DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
- char chType, int nWidth, int nDecimals )
-
+int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle psDBF, const char *pszFieldName,
+ char chType, int nWidth, int nDecimals)
{
- char *pszFInfo;
- int i;
- int nOldRecordLength, nOldHeaderLength;
- char *pszRecord;
- char chFieldFill;
- SAOffset nRecordOffset;
-
/* make sure that everything is written in .dbf */
- if( !DBFFlushRecord( psDBF ) )
+ if (!DBFFlushRecord(psDBF))
return -1;
- if( psDBF->nHeaderLength + XBASE_FLDHDR_SZ > 65535 )
+ if (psDBF->nHeaderLength + XBASE_FLDHDR_SZ > 65535)
{
char szMessage[128];
- snprintf( szMessage, sizeof(szMessage),
- "Cannot add field %s. Header length limit reached "
- "(max 65535 bytes, 2046 fields).",
- pszFieldName );
- psDBF->sHooks.Error( szMessage );
+ snprintf(szMessage, sizeof(szMessage),
+ "Cannot add field %s. Header length limit reached "
+ "(max 65535 bytes, 2046 fields).",
+ pszFieldName);
+ psDBF->sHooks.Error(szMessage);
return -1;
}
-/* -------------------------------------------------------------------- */
-/* Do some checking to ensure we can add records to this file. */
-/* -------------------------------------------------------------------- */
- if( nWidth < 1 )
+ /* -------------------------------------------------------------------- */
+ /* Do some checking to ensure we can add records to this file. */
+ /* -------------------------------------------------------------------- */
+ if (nWidth < 1)
return -1;
- if( nWidth > XBASE_FLD_MAX_WIDTH )
+ if (nWidth > XBASE_FLD_MAX_WIDTH)
nWidth = XBASE_FLD_MAX_WIDTH;
- if( psDBF->nRecordLength + nWidth > 65535 )
+ if (psDBF->nRecordLength + nWidth > 65535)
{
char szMessage[128];
- snprintf( szMessage, sizeof(szMessage),
- "Cannot add field %s. Record length limit reached "
- "(max 65535 bytes).",
- pszFieldName );
- psDBF->sHooks.Error( szMessage );
+ snprintf(szMessage, sizeof(szMessage),
+ "Cannot add field %s. Record length limit reached "
+ "(max 65535 bytes).",
+ pszFieldName);
+ psDBF->sHooks.Error(szMessage);
return -1;
}
- nOldRecordLength = psDBF->nRecordLength;
- nOldHeaderLength = psDBF->nHeaderLength;
+ const int nOldRecordLength = psDBF->nRecordLength;
+ const int nOldHeaderLength = psDBF->nHeaderLength;
-/* -------------------------------------------------------------------- */
-/* SfRealloc all the arrays larger to hold the additional field */
-/* information. */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* realloc all the arrays larger to hold the additional field */
+ /* information. */
+ /* -------------------------------------------------------------------- */
psDBF->nFields++;
- psDBF->panFieldOffset = STATIC_CAST(int *,
- SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields ));
+ psDBF->panFieldOffset = STATIC_CAST(
+ int *, realloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields));
- psDBF->panFieldSize = STATIC_CAST(int *,
- SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields ));
+ psDBF->panFieldSize = STATIC_CAST(
+ int *, realloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields));
- psDBF->panFieldDecimals = STATIC_CAST(int *,
- SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields ));
+ psDBF->panFieldDecimals = STATIC_CAST(
+ int *, realloc(psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields));
- psDBF->pachFieldType = STATIC_CAST(char *,
- SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields ));
+ psDBF->pachFieldType = STATIC_CAST(
+ char *, realloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields));
-/* -------------------------------------------------------------------- */
-/* Assign the new field information fields. */
-/* -------------------------------------------------------------------- */
- psDBF->panFieldOffset[psDBF->nFields-1] = psDBF->nRecordLength;
+ /* -------------------------------------------------------------------- */
+ /* Assign the new field information fields. */
+ /* -------------------------------------------------------------------- */
+ psDBF->panFieldOffset[psDBF->nFields - 1] = psDBF->nRecordLength;
psDBF->nRecordLength += nWidth;
- psDBF->panFieldSize[psDBF->nFields-1] = nWidth;
- psDBF->panFieldDecimals[psDBF->nFields-1] = nDecimals;
- psDBF->pachFieldType[psDBF->nFields-1] = chType;
+ psDBF->panFieldSize[psDBF->nFields - 1] = nWidth;
+ psDBF->panFieldDecimals[psDBF->nFields - 1] = nDecimals;
+ psDBF->pachFieldType[psDBF->nFields - 1] = chType;
-/* -------------------------------------------------------------------- */
-/* Extend the required header information. */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* Extend the required header information. */
+ /* -------------------------------------------------------------------- */
psDBF->nHeaderLength += XBASE_FLDHDR_SZ;
psDBF->bUpdated = FALSE;
- psDBF->pszHeader = STATIC_CAST(char *, SfRealloc(psDBF->pszHeader,
- psDBF->nFields*XBASE_FLDHDR_SZ));
+ psDBF->pszHeader = STATIC_CAST(
+ char *, realloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ));
- pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields-1);
+ char *pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields - 1);
- for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
+ for (int i = 0; i < XBASE_FLDHDR_SZ; i++)
pszFInfo[i] = '\0';
- strncpy( pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE );
+ strncpy(pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE);
- pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
+ pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields - 1];
- if( chType == 'C' )
+ if (chType == 'C')
{
pszFInfo[16] = STATIC_CAST(unsigned char, nWidth % 256);
pszFInfo[17] = STATIC_CAST(unsigned char, nWidth / 256);
pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
}
-/* -------------------------------------------------------------------- */
-/* Make the current record buffer appropriately larger. */
-/* -------------------------------------------------------------------- */
- psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
- psDBF->nRecordLength));
+ /* -------------------------------------------------------------------- */
+ /* Make the current record buffer appropriately larger. */
+ /* -------------------------------------------------------------------- */
+ psDBF->pszCurrentRecord = STATIC_CAST(
+ char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));
/* we're done if dealing with new .dbf */
- if( psDBF->bNoHeader )
- return( psDBF->nFields - 1 );
+ if (psDBF->bNoHeader)
+ return (psDBF->nFields - 1);
-/* -------------------------------------------------------------------- */
-/* For existing .dbf file, shift records */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* For existing .dbf file, shift records */
+ /* -------------------------------------------------------------------- */
/* alloc record */
- pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+ char *pszRecord =
+ STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
- chFieldFill = DBFGetNullCharacter(chType);
+ const char chFieldFill = DBFGetNullCharacter(chType);
- for (i = psDBF->nRecords-1; i >= 0; --i)
+ SAOffset nRecordOffset;
+ for (int i = psDBF->nRecords - 1; i >= 0; --i)
{
- nRecordOffset = nOldRecordLength * STATIC_CAST(SAOffset, i) + nOldHeaderLength;
+ nRecordOffset =
+ nOldRecordLength * STATIC_CAST(SAOffset, i) + nOldHeaderLength;
/* load record */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ if (psDBF->sHooks.FRead(pszRecord, nOldRecordLength, 1, psDBF->fp) != 1)
+ {
+ free(pszRecord);
+ return -1;
+ }
/* set new field's value to NULL */
memset(pszRecord + nOldRecordLength, chFieldFill, nWidth);
- nRecordOffset = psDBF->nRecordLength * STATIC_CAST(SAOffset, i) + psDBF->nHeaderLength;
+ nRecordOffset = psDBF->nRecordLength * STATIC_CAST(SAOffset, i) +
+ psDBF->nHeaderLength;
/* move record to the new place*/
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ psDBF->sHooks.FWrite(pszRecord, psDBF->nRecordLength, 1, psDBF->fp);
}
- if( psDBF->bWriteEndOfFileChar )
+ if (psDBF->bWriteEndOfFileChar)
{
char ch = END_OF_FILE_CHARACTER;
nRecordOffset =
- psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
+ psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nRecords) +
+ psDBF->nHeaderLength;
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
}
/* free record */
/* force update of header with new header, record length and new field */
psDBF->bNoHeader = TRUE;
- DBFUpdateHeader( psDBF );
+ DBFUpdateHeader(psDBF);
psDBF->nCurrentRecord = -1;
psDBF->bCurrentRecordModified = FALSE;
psDBF->bUpdated = TRUE;
- return( psDBF->nFields-1 );
+ return (psDBF->nFields - 1);
}
/************************************************************************/
/************************************************************************/
static void *DBFReadAttribute(DBFHandle psDBF, int hEntity, int iField,
- char chReqType )
-
+ char chReqType)
{
- unsigned char *pabyRec;
- void *pReturnField = SHPLIB_NULLPTR;
-
-/* -------------------------------------------------------------------- */
-/* Verify selection. */
-/* -------------------------------------------------------------------- */
- if( hEntity < 0 || hEntity >= psDBF->nRecords )
+ /* -------------------------------------------------------------------- */
+ /* Verify selection. */
+ /* -------------------------------------------------------------------- */
+ if (hEntity < 0 || hEntity >= psDBF->nRecords)
return SHPLIB_NULLPTR;
- if( iField < 0 || iField >= psDBF->nFields )
+ if (iField < 0 || iField >= psDBF->nFields)
return SHPLIB_NULLPTR;
-/* -------------------------------------------------------------------- */
-/* Have we read the record? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, hEntity ) )
+ /* -------------------------------------------------------------------- */
+ /* Have we read the record? */
+ /* -------------------------------------------------------------------- */
+ if (!DBFLoadRecord(psDBF, hEntity))
return SHPLIB_NULLPTR;
- pabyRec = REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
+ const unsigned char *pabyRec =
+ REINTERPRET_CAST(const unsigned char *, psDBF->pszCurrentRecord);
-/* -------------------------------------------------------------------- */
-/* Ensure we have room to extract the target field. */
-/* -------------------------------------------------------------------- */
- if( psDBF->panFieldSize[iField] >= psDBF->nWorkFieldLength )
+ /* -------------------------------------------------------------------- */
+ /* Ensure we have room to extract the target field. */
+ /* -------------------------------------------------------------------- */
+ if (psDBF->panFieldSize[iField] >= psDBF->nWorkFieldLength)
{
psDBF->nWorkFieldLength = psDBF->panFieldSize[iField] + 100;
- if( psDBF->pszWorkField == SHPLIB_NULLPTR )
- psDBF->pszWorkField = STATIC_CAST(char *, malloc(psDBF->nWorkFieldLength));
+ if (psDBF->pszWorkField == SHPLIB_NULLPTR)
+ psDBF->pszWorkField =
+ STATIC_CAST(char *, malloc(psDBF->nWorkFieldLength));
else
- psDBF->pszWorkField = STATIC_CAST(char *, realloc(psDBF->pszWorkField,
- psDBF->nWorkFieldLength));
+ psDBF->pszWorkField = STATIC_CAST(
+ char *, realloc(psDBF->pszWorkField, psDBF->nWorkFieldLength));
}
-/* -------------------------------------------------------------------- */
-/* Extract the requested field. */
-/* -------------------------------------------------------------------- */
- memcpy( psDBF->pszWorkField,
- REINTERPRET_CAST(const char *, pabyRec) + psDBF->panFieldOffset[iField],
- psDBF->panFieldSize[iField] );
+ /* -------------------------------------------------------------------- */
+ /* Extract the requested field. */
+ /* -------------------------------------------------------------------- */
+ memcpy(psDBF->pszWorkField,
+ REINTERPRET_CAST(const char *, pabyRec) +
+ psDBF->panFieldOffset[iField],
+ psDBF->panFieldSize[iField]);
psDBF->pszWorkField[psDBF->panFieldSize[iField]] = '\0';
- pReturnField = psDBF->pszWorkField;
+ void *pReturnField = psDBF->pszWorkField;
-/* -------------------------------------------------------------------- */
-/* Decode the field. */
-/* -------------------------------------------------------------------- */
- if( chReqType == 'I' )
+ /* -------------------------------------------------------------------- */
+ /* Decode the field. */
+ /* -------------------------------------------------------------------- */
+ if (chReqType == 'I')
{
psDBF->fieldValue.nIntField = atoi(psDBF->pszWorkField);
pReturnField = &(psDBF->fieldValue.nIntField);
}
- else if( chReqType == 'N' )
+ else if (chReqType == 'N')
{
- psDBF->fieldValue.dfDoubleField = psDBF->sHooks.Atof(psDBF->pszWorkField);
+ psDBF->fieldValue.dfDoubleField =
+ psDBF->sHooks.Atof(psDBF->pszWorkField);
pReturnField = &(psDBF->fieldValue.dfDoubleField);
}
#ifdef TRIM_DBF_WHITESPACE
else
{
- char *pchSrc, *pchDst;
+ char *pchSrc = psDBF->pszWorkField;
+ char *pchDst = pchSrc;
- pchDst = pchSrc = psDBF->pszWorkField;
- while( *pchSrc == ' ' )
+ while (*pchSrc == ' ')
pchSrc++;
- while( *pchSrc != '\0' )
+ while (*pchSrc != '\0')
*(pchDst++) = *(pchSrc++);
*pchDst = '\0';
- while( pchDst != psDBF->pszWorkField && *(--pchDst) == ' ' )
+ while (pchDst != psDBF->pszWorkField && *(--pchDst) == ' ')
*pchDst = '\0';
}
#endif
/* Read an integer attribute. */
/************************************************************************/
-int SHPAPI_CALL
-DBFReadIntegerAttribute( DBFHandle psDBF, int iRecord, int iField )
-
+int SHPAPI_CALL DBFReadIntegerAttribute(DBFHandle psDBF, int iRecord,
+ int iField)
{
- int *pnValue;
-
- pnValue = STATIC_CAST(int *, DBFReadAttribute( psDBF, iRecord, iField, 'I' ));
+ int *pnValue =
+ STATIC_CAST(int *, DBFReadAttribute(psDBF, iRecord, iField, 'I'));
- if( pnValue == SHPLIB_NULLPTR )
+ if (pnValue == SHPLIB_NULLPTR)
return 0;
else
return *pnValue;
/* Read a double attribute. */
/************************************************************************/
-double SHPAPI_CALL
-DBFReadDoubleAttribute( DBFHandle psDBF, int iRecord, int iField )
-
+double SHPAPI_CALL DBFReadDoubleAttribute(DBFHandle psDBF, int iRecord,
+ int iField)
{
- double *pdValue;
-
- pdValue = STATIC_CAST(double *, DBFReadAttribute( psDBF, iRecord, iField, 'N' ));
+ double *pdValue =
+ STATIC_CAST(double *, DBFReadAttribute(psDBF, iRecord, iField, 'N'));
- if( pdValue == SHPLIB_NULLPTR )
+ if (pdValue == SHPLIB_NULLPTR)
return 0.0;
else
- return *pdValue ;
+ return *pdValue;
}
/************************************************************************/
/************************************************************************/
const char SHPAPI_CALL1(*)
-DBFReadStringAttribute( DBFHandle psDBF, int iRecord, int iField )
+ DBFReadStringAttribute(DBFHandle psDBF, int iRecord, int iField)
{
- return STATIC_CAST(const char *, DBFReadAttribute( psDBF, iRecord, iField, 'C' ) );
+ return STATIC_CAST(const char *,
+ DBFReadAttribute(psDBF, iRecord, iField, 'C'));
}
/************************************************************************/
/************************************************************************/
const char SHPAPI_CALL1(*)
-DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
+ DBFReadLogicalAttribute(DBFHandle psDBF, int iRecord, int iField)
{
- return STATIC_CAST(const char *, DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
+ return STATIC_CAST(const char *,
+ DBFReadAttribute(psDBF, iRecord, iField, 'L'));
}
-
/************************************************************************/
/* DBFIsValueNULL() */
/* */
/* Return TRUE if the passed string is NULL. */
/************************************************************************/
-static int DBFIsValueNULL( char chType, const char* pszValue )
+static bool DBFIsValueNULL(char chType, const char *pszValue)
{
- int i;
-
- if( pszValue == SHPLIB_NULLPTR )
- return TRUE;
+ if (pszValue == SHPLIB_NULLPTR)
+ return true;
- switch(chType)
+ switch (chType)
{
- case 'N':
- case 'F':
- /*
- ** We accept all asterisks or all blanks as NULL
- ** though according to the spec I think it should be all
- ** asterisks.
- */
- if( pszValue[0] == '*' )
- return TRUE;
-
- for( i = 0; pszValue[i] != '\0'; i++ )
- {
- if( pszValue[i] != ' ' )
- return FALSE;
- }
- return TRUE;
-
- case 'D':
- /* NULL date fields have value "00000000" */
- return strncmp(pszValue,"00000000",8) == 0;
-
- case 'L':
- /* NULL boolean fields have value "?" */
- return pszValue[0] == '?';
-
- default:
- /* empty string fields are considered NULL */
- return strlen(pszValue) == 0;
+ case 'N':
+ case 'F':
+ /*
+ ** We accept all asterisks or all blanks as NULL
+ ** though according to the spec I think it should be all
+ ** asterisks.
+ */
+ if (pszValue[0] == '*')
+ return true;
+
+ for (int i = 0; pszValue[i] != '\0'; i++)
+ {
+ if (pszValue[i] != ' ')
+ return false;
+ }
+ return true;
+
+ case 'D':
+ /* NULL date fields have value "00000000" */
+ /* Some DBF files have fields filled with spaces */
+ /* (trimmed by DBFReadStringAttribute) to indicate null */
+ /* values for dates (#4265). */
+ /* And others have ' 0': https://lists.osgeo.org/pipermail/gdal-dev/2023-November/058010.html */
+ return strncmp(pszValue, "00000000", 8) == 0 ||
+ strcmp(pszValue, " ") == 0 || strcmp(pszValue, "0") == 0;
+
+ case 'L':
+ /* NULL boolean fields have value "?" */
+ return pszValue[0] == '?';
+
+ default:
+ /* empty string fields are considered NULL */
+ return strlen(pszValue) == 0;
}
}
/* Contributed by Jim Matthews. */
/************************************************************************/
-int SHPAPI_CALL
-DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
-
+int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle psDBF, int iRecord, int iField)
{
- const char *pszValue;
-
- pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
+ const char *pszValue = DBFReadStringAttribute(psDBF, iRecord, iField);
- if( pszValue == SHPLIB_NULLPTR )
+ if (pszValue == SHPLIB_NULLPTR)
return TRUE;
- return DBFIsValueNULL( psDBF->pachFieldType[iField], pszValue );
+ return DBFIsValueNULL(psDBF->pachFieldType[iField], pszValue);
}
/************************************************************************/
/* Return the number of fields in this table. */
/************************************************************************/
-int SHPAPI_CALL
-DBFGetFieldCount( DBFHandle psDBF )
+int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF)
{
- return( psDBF->nFields );
+ return (psDBF->nFields);
}
/************************************************************************/
/* Return the number of records in this table. */
/************************************************************************/
-int SHPAPI_CALL
-DBFGetRecordCount( DBFHandle psDBF )
+int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF)
{
- return( psDBF->nRecords );
+ return (psDBF->nRecords);
}
/************************************************************************/
/* bytes long. */
/************************************************************************/
-DBFFieldType SHPAPI_CALL
-DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
- int * pnWidth, int * pnDecimals )
+DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField,
+ char *pszFieldName, int *pnWidth,
+ int *pnDecimals)
{
- if( iField < 0 || iField >= psDBF->nFields )
- return( FTInvalid );
+ if (iField < 0 || iField >= psDBF->nFields)
+ return (FTInvalid);
- if( pnWidth != SHPLIB_NULLPTR )
+ if (pnWidth != SHPLIB_NULLPTR)
*pnWidth = psDBF->panFieldSize[iField];
- if( pnDecimals != SHPLIB_NULLPTR )
+ if (pnDecimals != SHPLIB_NULLPTR)
*pnDecimals = psDBF->panFieldDecimals[iField];
- if( pszFieldName != SHPLIB_NULLPTR )
+ if (pszFieldName != SHPLIB_NULLPTR)
{
- int i;
-
- strncpy( pszFieldName, STATIC_CAST(char *,psDBF->pszHeader)+iField*XBASE_FLDHDR_SZ,
- XBASE_FLDNAME_LEN_READ );
- pszFieldName[XBASE_FLDNAME_LEN_READ] = '\0';
- for( i = XBASE_FLDNAME_LEN_READ - 1; i > 0 && pszFieldName[i] == ' '; i-- )
- pszFieldName[i] = '\0';
+ strncpy(pszFieldName,
+ STATIC_CAST(char *, psDBF->pszHeader) +
+ iField * XBASE_FLDHDR_SZ,
+ XBASE_FLDNAME_LEN_READ);
+ pszFieldName[XBASE_FLDNAME_LEN_READ] = '\0';
+ for (int i = XBASE_FLDNAME_LEN_READ - 1;
+ i > 0 && pszFieldName[i] == ' '; i--)
+ pszFieldName[i] = '\0';
}
- if ( psDBF->pachFieldType[iField] == 'L' )
- return( FTLogical );
+ if (psDBF->pachFieldType[iField] == 'L')
+ return (FTLogical);
- else if( psDBF->pachFieldType[iField] == 'D' )
- return( FTDate );
+ else if (psDBF->pachFieldType[iField] == 'D')
+ return (FTDate);
- else if( psDBF->pachFieldType[iField] == 'N'
- || psDBF->pachFieldType[iField] == 'F' )
+ else if (psDBF->pachFieldType[iField] == 'N' ||
+ psDBF->pachFieldType[iField] == 'F')
{
- if( psDBF->panFieldDecimals[iField] > 0
- || psDBF->panFieldSize[iField] >= 10 )
- return( FTDouble );
- else
- return( FTInteger );
+ if (psDBF->panFieldDecimals[iField] > 0 ||
+ psDBF->panFieldSize[iField] >= 10)
+ return (FTDouble);
+ else
+ return (FTInteger);
}
else
{
- return( FTString );
+ return (FTString);
}
}
/************************************************************************/
/* DBFWriteAttribute() */
-/* */
-/* Write an attribute record to the file. */
+/* */
+/* Write an attribute record to the file. */
/************************************************************************/
-static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
- void * pValue )
-
+static bool DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
+ void *pValue)
{
- int i, j, nRetResult = TRUE;
- unsigned char *pabyRec;
- char szSField[XBASE_FLD_MAX_WIDTH+1], szFormat[20];
-
-/* -------------------------------------------------------------------- */
-/* Is this a valid record? */
-/* -------------------------------------------------------------------- */
- if( hEntity < 0 || hEntity > psDBF->nRecords )
- return( FALSE );
+ /* -------------------------------------------------------------------- */
+ /* Is this a valid record? */
+ /* -------------------------------------------------------------------- */
+ if (hEntity < 0 || hEntity > psDBF->nRecords)
+ return false;
- if( psDBF->bNoHeader )
+ if (psDBF->bNoHeader)
DBFWriteHeader(psDBF);
-/* -------------------------------------------------------------------- */
-/* Is this a brand new record? */
-/* -------------------------------------------------------------------- */
- if( hEntity == psDBF->nRecords )
+ /* -------------------------------------------------------------------- */
+ /* Is this a brand new record? */
+ /* -------------------------------------------------------------------- */
+ if (hEntity == psDBF->nRecords)
{
- if( !DBFFlushRecord( psDBF ) )
- return FALSE;
+ if (!DBFFlushRecord(psDBF))
+ return false;
- psDBF->nRecords++;
- for( i = 0; i < psDBF->nRecordLength; i++ )
- psDBF->pszCurrentRecord[i] = ' ';
+ psDBF->nRecords++;
+ for (int i = 0; i < psDBF->nRecordLength; i++)
+ psDBF->pszCurrentRecord[i] = ' ';
- psDBF->nCurrentRecord = hEntity;
+ psDBF->nCurrentRecord = hEntity;
}
-/* -------------------------------------------------------------------- */
-/* Is this an existing record, but different than the last one */
-/* we accessed? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, hEntity ) )
- return FALSE;
+ /* -------------------------------------------------------------------- */
+ /* Is this an existing record, but different than the last one */
+ /* we accessed? */
+ /* -------------------------------------------------------------------- */
+ if (!DBFLoadRecord(psDBF, hEntity))
+ return false;
- pabyRec = REINTERPRET_CAST(unsigned char *,psDBF->pszCurrentRecord);
+ unsigned char *pabyRec =
+ REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
psDBF->bCurrentRecordModified = TRUE;
psDBF->bUpdated = TRUE;
-/* -------------------------------------------------------------------- */
-/* Translate NULL value to valid DBF file representation. */
-/* */
-/* Contributed by Jim Matthews. */
-/* -------------------------------------------------------------------- */
- if( pValue == SHPLIB_NULLPTR )
+ /* -------------------------------------------------------------------- */
+ /* Translate NULL value to valid DBF file representation. */
+ /* */
+ /* Contributed by Jim Matthews. */
+ /* -------------------------------------------------------------------- */
+ if (pValue == SHPLIB_NULLPTR)
{
- memset( pabyRec+psDBF->panFieldOffset[iField],
- DBFGetNullCharacter(psDBF->pachFieldType[iField]),
- psDBF->panFieldSize[iField] );
- return TRUE;
+ memset(pabyRec + psDBF->panFieldOffset[iField],
+ DBFGetNullCharacter(psDBF->pachFieldType[iField]),
+ psDBF->panFieldSize[iField]);
+ return true;
}
-/* -------------------------------------------------------------------- */
-/* Assign all the record fields. */
-/* -------------------------------------------------------------------- */
- switch( psDBF->pachFieldType[iField] )
+ /* -------------------------------------------------------------------- */
+ /* Assign all the record fields. */
+ /* -------------------------------------------------------------------- */
+ bool nRetResult = true;
+
+ switch (psDBF->pachFieldType[iField])
{
- case 'D':
- case 'N':
- case 'F':
- {
- int nWidth = psDBF->panFieldSize[iField];
-
- if( STATIC_CAST(int,sizeof(szSField))-2 < nWidth )
- nWidth = sizeof(szSField)-2;
-
- snprintf( szFormat, sizeof(szFormat), "%%%d.%df",
- nWidth, psDBF->panFieldDecimals[iField] );
- CPLsnprintf(szSField, sizeof(szSField), szFormat, *STATIC_CAST(double *, pValue) );
- szSField[sizeof(szSField)-1] = '\0';
- if( STATIC_CAST(int,strlen(szSField)) > psDBF->panFieldSize[iField] )
+ case 'D':
+ case 'N':
+ case 'F':
{
- szSField[psDBF->panFieldSize[iField]] = '\0';
- nRetResult = FALSE;
- }
- strncpy(REINTERPRET_CAST(char *, pabyRec+psDBF->panFieldOffset[iField]),
- szSField, strlen(szSField) );
- break;
- }
-
- case 'L':
- if (psDBF->panFieldSize[iField] >= 1 &&
- (*STATIC_CAST(char*,pValue) == 'F' || *STATIC_CAST(char*,pValue) == 'T'))
- *(pabyRec+psDBF->panFieldOffset[iField]) = *STATIC_CAST(char*,pValue);
- break;
-
- default:
- if( STATIC_CAST(int, strlen(STATIC_CAST(char *,pValue))) > psDBF->panFieldSize[iField] )
- {
- j = psDBF->panFieldSize[iField];
- nRetResult = FALSE;
+ int nWidth = psDBF->panFieldSize[iField];
+
+ char szSField[XBASE_FLD_MAX_WIDTH + 1];
+ if (STATIC_CAST(int, sizeof(szSField)) - 2 < nWidth)
+ nWidth = sizeof(szSField) - 2;
+
+ char szFormat[20];
+ snprintf(szFormat, sizeof(szFormat), "%%%d.%df", nWidth,
+ psDBF->panFieldDecimals[iField]);
+ CPLsnprintf(szSField, sizeof(szSField), szFormat,
+ *STATIC_CAST(double *, pValue));
+ szSField[sizeof(szSField) - 1] = '\0';
+ if (STATIC_CAST(int, strlen(szSField)) >
+ psDBF->panFieldSize[iField])
+ {
+ szSField[psDBF->panFieldSize[iField]] = '\0';
+ nRetResult = false;
+ }
+ memcpy(REINTERPRET_CAST(char *,
+ pabyRec + psDBF->panFieldOffset[iField]),
+ szSField, strlen(szSField));
+ break;
}
- else
+
+ case 'L':
+ if (psDBF->panFieldSize[iField] >= 1 &&
+ (*STATIC_CAST(char *, pValue) == 'F' ||
+ *STATIC_CAST(char *, pValue) == 'T'))
+ *(pabyRec + psDBF->panFieldOffset[iField]) =
+ *STATIC_CAST(char *, pValue);
+ break;
+
+ default:
{
- memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
- psDBF->panFieldSize[iField] );
- j = STATIC_CAST(int, strlen(STATIC_CAST(char *,pValue)));
- }
+ int j;
+ if (STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue))) >
+ psDBF->panFieldSize[iField])
+ {
+ j = psDBF->panFieldSize[iField];
+ nRetResult = false;
+ }
+ else
+ {
+ memset(pabyRec + psDBF->panFieldOffset[iField], ' ',
+ psDBF->panFieldSize[iField]);
+ j = STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue)));
+ }
- strncpy(REINTERPRET_CAST(char *, pabyRec+psDBF->panFieldOffset[iField]),
- STATIC_CAST(const char *, pValue), j );
- break;
+ strncpy(REINTERPRET_CAST(char *,
+ pabyRec + psDBF->panFieldOffset[iField]),
+ STATIC_CAST(const char *, pValue), j);
+ break;
+ }
}
- return( nRetResult );
+ return nRetResult;
}
/************************************************************************/
/* as is to the field position in the record. */
/************************************************************************/
-int SHPAPI_CALL
-DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
- void * pValue )
-
+int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity,
+ int iField, const void *pValue)
{
- int i, j;
- unsigned char *pabyRec;
+ /* -------------------------------------------------------------------- */
+ /* Is this a valid record? */
+ /* -------------------------------------------------------------------- */
+ if (hEntity < 0 || hEntity > psDBF->nRecords)
+ return (FALSE);
-/* -------------------------------------------------------------------- */
-/* Is this a valid record? */
-/* -------------------------------------------------------------------- */
- if( hEntity < 0 || hEntity > psDBF->nRecords )
- return( FALSE );
-
- if( psDBF->bNoHeader )
+ if (psDBF->bNoHeader)
DBFWriteHeader(psDBF);
-/* -------------------------------------------------------------------- */
-/* Is this a brand new record? */
-/* -------------------------------------------------------------------- */
- if( hEntity == psDBF->nRecords )
+ /* -------------------------------------------------------------------- */
+ /* Is this a brand new record? */
+ /* -------------------------------------------------------------------- */
+ if (hEntity == psDBF->nRecords)
{
- if( !DBFFlushRecord( psDBF ) )
+ if (!DBFFlushRecord(psDBF))
return FALSE;
- psDBF->nRecords++;
- for( i = 0; i < psDBF->nRecordLength; i++ )
- psDBF->pszCurrentRecord[i] = ' ';
+ psDBF->nRecords++;
+ for (int i = 0; i < psDBF->nRecordLength; i++)
+ psDBF->pszCurrentRecord[i] = ' ';
- psDBF->nCurrentRecord = hEntity;
+ psDBF->nCurrentRecord = hEntity;
}
-/* -------------------------------------------------------------------- */
-/* Is this an existing record, but different than the last one */
-/* we accessed? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, hEntity ) )
+ /* -------------------------------------------------------------------- */
+ /* Is this an existing record, but different than the last one */
+ /* we accessed? */
+ /* -------------------------------------------------------------------- */
+ if (!DBFLoadRecord(psDBF, hEntity))
return FALSE;
- pabyRec = REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
-
-/* -------------------------------------------------------------------- */
-/* Assign all the record fields. */
-/* -------------------------------------------------------------------- */
- if( STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue))) > psDBF->panFieldSize[iField] )
- j = psDBF->panFieldSize[iField];
- else
+ if (iField >= 0)
{
- memset( pabyRec+psDBF->panFieldOffset[iField], ' ',
- psDBF->panFieldSize[iField] );
- j = STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue)));
- }
+ unsigned char *pabyRec =
+ REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
+
+ /* -------------------------------------------------------------------- */
+ /* Assign all the record fields. */
+ /* -------------------------------------------------------------------- */
+ int j;
+ if (STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue))) >
+ psDBF->panFieldSize[iField])
+ j = psDBF->panFieldSize[iField];
+ else
+ {
+ memset(pabyRec + psDBF->panFieldOffset[iField], ' ',
+ psDBF->panFieldSize[iField]);
+ j = STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue)));
+ }
- strncpy(REINTERPRET_CAST(char *, pabyRec+psDBF->panFieldOffset[iField]),
- STATIC_CAST(const char *, pValue), j );
+ strncpy(
+ REINTERPRET_CAST(char *, pabyRec + psDBF->panFieldOffset[iField]),
+ STATIC_CAST(const char *, pValue), j);
+ }
psDBF->bCurrentRecordModified = TRUE;
psDBF->bUpdated = TRUE;
- return( TRUE );
+ return (TRUE);
}
/************************************************************************/
/* Write a double attribute. */
/************************************************************************/
-int SHPAPI_CALL
-DBFWriteDoubleAttribute( DBFHandle psDBF, int iRecord, int iField,
- double dValue )
-
+int SHPAPI_CALL DBFWriteDoubleAttribute(DBFHandle psDBF, int iRecord,
+ int iField, double dValue)
{
- return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, &dValue) ) );
+ return (DBFWriteAttribute(psDBF, iRecord, iField,
+ STATIC_CAST(void *, &dValue)));
}
/************************************************************************/
/* Write a integer attribute. */
/************************************************************************/
-int SHPAPI_CALL
-DBFWriteIntegerAttribute( DBFHandle psDBF, int iRecord, int iField,
- int nValue )
-
+int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle psDBF, int iRecord,
+ int iField, int nValue)
{
- double dValue = nValue;
+ double dValue = nValue;
- return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, &dValue) ) );
+ return (DBFWriteAttribute(psDBF, iRecord, iField,
+ STATIC_CAST(void *, &dValue)));
}
/************************************************************************/
/* Write a string attribute. */
/************************************************************************/
-int SHPAPI_CALL
-DBFWriteStringAttribute( DBFHandle psDBF, int iRecord, int iField,
- const char * pszValue )
+int SHPAPI_CALL DBFWriteStringAttribute(DBFHandle psDBF, int iRecord,
+ int iField, const char *pszValue)
{
- return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, CONST_CAST(char*, pszValue))) );
+ return (
+ DBFWriteAttribute(psDBF, iRecord, iField,
+ STATIC_CAST(void *, CONST_CAST(char *, pszValue))));
}
/************************************************************************/
/* Write a string attribute. */
/************************************************************************/
-int SHPAPI_CALL
-DBFWriteNULLAttribute( DBFHandle psDBF, int iRecord, int iField )
+int SHPAPI_CALL DBFWriteNULLAttribute(DBFHandle psDBF, int iRecord, int iField)
{
- return( DBFWriteAttribute( psDBF, iRecord, iField, SHPLIB_NULLPTR ) );
+ return (DBFWriteAttribute(psDBF, iRecord, iField, SHPLIB_NULLPTR));
}
/************************************************************************/
/* Write a logical attribute. */
/************************************************************************/
-int SHPAPI_CALL
-DBFWriteLogicalAttribute( DBFHandle psDBF, int iRecord, int iField,
- const char lValue)
+int SHPAPI_CALL DBFWriteLogicalAttribute(DBFHandle psDBF, int iRecord,
+ int iField, const char lValue)
{
- return( DBFWriteAttribute( psDBF, iRecord, iField, STATIC_CAST(void *, CONST_CAST(char*, &lValue)) ) );
+ return (
+ DBFWriteAttribute(psDBF, iRecord, iField,
+ STATIC_CAST(void *, CONST_CAST(char *, &lValue))));
}
/************************************************************************/
/* DBFWriteTuple() */
-/* */
-/* Write an attribute record to the file. */
+/* */
+/* Write an attribute record to the file. */
/************************************************************************/
-int SHPAPI_CALL
-DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple )
-
+int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity,
+ const void *pRawTuple)
{
- int i;
- unsigned char *pabyRec;
+ /* -------------------------------------------------------------------- */
+ /* Is this a valid record? */
+ /* -------------------------------------------------------------------- */
+ if (hEntity < 0 || hEntity > psDBF->nRecords)
+ return (FALSE);
-/* -------------------------------------------------------------------- */
-/* Is this a valid record? */
-/* -------------------------------------------------------------------- */
- if( hEntity < 0 || hEntity > psDBF->nRecords )
- return( FALSE );
-
- if( psDBF->bNoHeader )
+ if (psDBF->bNoHeader)
DBFWriteHeader(psDBF);
-/* -------------------------------------------------------------------- */
-/* Is this a brand new record? */
-/* -------------------------------------------------------------------- */
- if( hEntity == psDBF->nRecords )
+ /* -------------------------------------------------------------------- */
+ /* Is this a brand new record? */
+ /* -------------------------------------------------------------------- */
+ if (hEntity == psDBF->nRecords)
{
- if( !DBFFlushRecord( psDBF ) )
+ if (!DBFFlushRecord(psDBF))
return FALSE;
- psDBF->nRecords++;
- for( i = 0; i < psDBF->nRecordLength; i++ )
- psDBF->pszCurrentRecord[i] = ' ';
+ psDBF->nRecords++;
+ for (int i = 0; i < psDBF->nRecordLength; i++)
+ psDBF->pszCurrentRecord[i] = ' ';
- psDBF->nCurrentRecord = hEntity;
+ psDBF->nCurrentRecord = hEntity;
}
-/* -------------------------------------------------------------------- */
-/* Is this an existing record, but different than the last one */
-/* we accessed? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, hEntity ) )
+ /* -------------------------------------------------------------------- */
+ /* Is this an existing record, but different than the last one */
+ /* we accessed? */
+ /* -------------------------------------------------------------------- */
+ if (!DBFLoadRecord(psDBF, hEntity))
return FALSE;
- pabyRec = REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
+ unsigned char *pabyRec =
+ REINTERPRET_CAST(unsigned char *, psDBF->pszCurrentRecord);
- memcpy ( pabyRec, pRawTuple, psDBF->nRecordLength );
+ memcpy(pabyRec, pRawTuple, psDBF->nRecordLength);
psDBF->bCurrentRecordModified = TRUE;
psDBF->bUpdated = TRUE;
- return( TRUE );
+ return (TRUE);
}
/************************************************************************/
/* till the next record read for any reason. */
/************************************************************************/
-const char SHPAPI_CALL1(*)
-DBFReadTuple(DBFHandle psDBF, int hEntity )
+const char SHPAPI_CALL1(*) DBFReadTuple(DBFHandle psDBF, int hEntity)
{
- if( hEntity < 0 || hEntity >= psDBF->nRecords )
+ if (hEntity < 0 || hEntity >= psDBF->nRecords)
return SHPLIB_NULLPTR;
- if( !DBFLoadRecord( psDBF, hEntity ) )
+ if (!DBFLoadRecord(psDBF, hEntity))
return SHPLIB_NULLPTR;
return STATIC_CAST(const char *, psDBF->pszCurrentRecord);
}
/************************************************************************/
-/* DBFCloneEmpty() */
+/* DBFCloneEmpty() */
/* */
/* Read one of the attribute fields of a record. */
/************************************************************************/
-DBFHandle SHPAPI_CALL
-DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
+DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF, const char *pszFilename)
{
- DBFHandle newDBF;
-
- newDBF = DBFCreateEx ( pszFilename, psDBF->pszCodePage );
- if ( newDBF == SHPLIB_NULLPTR ) return SHPLIB_NULLPTR;
-
- newDBF->nFields = psDBF->nFields;
- newDBF->nRecordLength = psDBF->nRecordLength;
- newDBF->nHeaderLength = psDBF->nHeaderLength;
-
- if( psDBF->pszHeader )
- {
- newDBF->pszHeader = STATIC_CAST(char *, malloc ( XBASE_FLDHDR_SZ * psDBF->nFields ));
- memcpy ( newDBF->pszHeader, psDBF->pszHeader, XBASE_FLDHDR_SZ * psDBF->nFields );
- }
-
- newDBF->panFieldOffset = STATIC_CAST(int *, malloc ( sizeof(int) * psDBF->nFields ));
- memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
- newDBF->panFieldSize = STATIC_CAST(int *, malloc ( sizeof(int) * psDBF->nFields ));
- memcpy ( newDBF->panFieldSize, psDBF->panFieldSize, sizeof(int) * psDBF->nFields );
- newDBF->panFieldDecimals = STATIC_CAST(int *, malloc ( sizeof(int) * psDBF->nFields ));
- memcpy ( newDBF->panFieldDecimals, psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields );
- newDBF->pachFieldType = STATIC_CAST(char *, malloc ( sizeof(char) * psDBF->nFields ));
- memcpy ( newDBF->pachFieldType, psDBF->pachFieldType, sizeof(char)*psDBF->nFields );
-
- newDBF->bNoHeader = TRUE;
- newDBF->bUpdated = TRUE;
- newDBF->bWriteEndOfFileChar = psDBF->bWriteEndOfFileChar;
+ DBFHandle newDBF = DBFCreateEx(pszFilename, psDBF->pszCodePage);
+ if (newDBF == SHPLIB_NULLPTR)
+ return SHPLIB_NULLPTR;
- DBFWriteHeader ( newDBF );
- DBFClose ( newDBF );
+ newDBF->nFields = psDBF->nFields;
+ newDBF->nRecordLength = psDBF->nRecordLength;
+ newDBF->nHeaderLength = psDBF->nHeaderLength;
- newDBF = DBFOpen ( pszFilename, "rb+" );
- newDBF->bWriteEndOfFileChar = psDBF->bWriteEndOfFileChar;
+ if (psDBF->pszHeader)
+ {
+ newDBF->pszHeader =
+ STATIC_CAST(char *, malloc(XBASE_FLDHDR_SZ * psDBF->nFields));
+ memcpy(newDBF->pszHeader, psDBF->pszHeader,
+ XBASE_FLDHDR_SZ * psDBF->nFields);
+ }
- return ( newDBF );
+ newDBF->panFieldOffset =
+ STATIC_CAST(int *, malloc(sizeof(int) * psDBF->nFields));
+ memcpy(newDBF->panFieldOffset, psDBF->panFieldOffset,
+ sizeof(int) * psDBF->nFields);
+ newDBF->panFieldSize =
+ STATIC_CAST(int *, malloc(sizeof(int) * psDBF->nFields));
+ memcpy(newDBF->panFieldSize, psDBF->panFieldSize,
+ sizeof(int) * psDBF->nFields);
+ newDBF->panFieldDecimals =
+ STATIC_CAST(int *, malloc(sizeof(int) * psDBF->nFields));
+ memcpy(newDBF->panFieldDecimals, psDBF->panFieldDecimals,
+ sizeof(int) * psDBF->nFields);
+ newDBF->pachFieldType =
+ STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nFields));
+ memcpy(newDBF->pachFieldType, psDBF->pachFieldType,
+ sizeof(char) * psDBF->nFields);
+
+ newDBF->bNoHeader = TRUE;
+ newDBF->bUpdated = TRUE;
+ newDBF->bWriteEndOfFileChar = psDBF->bWriteEndOfFileChar;
+
+ DBFWriteHeader(newDBF);
+ DBFClose(newDBF);
+
+ newDBF = DBFOpen(pszFilename, "rb+");
+ newDBF->bWriteEndOfFileChar = psDBF->bWriteEndOfFileChar;
+
+ return (newDBF);
}
/************************************************************************/
/* 'M' (Memo: 10 digits .DBT block ptr) */
/************************************************************************/
-char SHPAPI_CALL
-DBFGetNativeFieldType( DBFHandle psDBF, int iField )
+char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle psDBF, int iField)
{
- if( iField >=0 && iField < psDBF->nFields )
+ if (iField >= 0 && iField < psDBF->nFields)
return psDBF->pachFieldType[iField];
- return ' ';
+ return ' ';
}
/************************************************************************/
/* Contributed by Jim Matthews. */
/************************************************************************/
-int SHPAPI_CALL
-DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
-
+int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
{
- char name[XBASE_FLDNAME_LEN_READ+1];
- int i;
+ char name[XBASE_FLDNAME_LEN_READ + 1];
- for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
+ for (int i = 0; i < DBFGetFieldCount(psDBF); i++)
{
- DBFGetFieldInfo( psDBF, i, name, SHPLIB_NULLPTR, SHPLIB_NULLPTR );
- if(!STRCASECMP(pszFieldName,name))
- return(i);
+ DBFGetFieldInfo(psDBF, i, name, SHPLIB_NULLPTR, SHPLIB_NULLPTR);
+ if (!STRCASECMP(pszFieldName, name))
+ return (i);
}
- return(-1);
+ return (-1);
}
/************************************************************************/
/* it returns FALSE. */
/************************************************************************/
-int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape )
-
+int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape)
{
-/* -------------------------------------------------------------------- */
-/* Verify selection. */
-/* -------------------------------------------------------------------- */
- if( iShape < 0 || iShape >= psDBF->nRecords )
+ /* -------------------------------------------------------------------- */
+ /* Verify selection. */
+ /* -------------------------------------------------------------------- */
+ if (iShape < 0 || iShape >= psDBF->nRecords)
return TRUE;
-/* -------------------------------------------------------------------- */
-/* Have we read the record? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, iShape ) )
+ /* -------------------------------------------------------------------- */
+ /* Have we read the record? */
+ /* -------------------------------------------------------------------- */
+ if (!DBFLoadRecord(psDBF, iShape))
return FALSE;
-/* -------------------------------------------------------------------- */
-/* '*' means deleted. */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* '*' means deleted. */
+ /* -------------------------------------------------------------------- */
return psDBF->pszCurrentRecord[0] == '*';
}
/* DBFMarkRecordDeleted() */
/************************************************************************/
-int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
- int bIsDeleted )
-
+int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape,
+ int bIsDeleted)
{
- char chNewFlag;
-
-/* -------------------------------------------------------------------- */
-/* Verify selection. */
-/* -------------------------------------------------------------------- */
- if( iShape < 0 || iShape >= psDBF->nRecords )
+ /* -------------------------------------------------------------------- */
+ /* Verify selection. */
+ /* -------------------------------------------------------------------- */
+ if (iShape < 0 || iShape >= psDBF->nRecords)
return FALSE;
-/* -------------------------------------------------------------------- */
-/* Is this an existing record, but different than the last one */
-/* we accessed? */
-/* -------------------------------------------------------------------- */
- if( !DBFLoadRecord( psDBF, iShape ) )
+ /* -------------------------------------------------------------------- */
+ /* Is this an existing record, but different than the last one */
+ /* we accessed? */
+ /* -------------------------------------------------------------------- */
+ if (!DBFLoadRecord(psDBF, iShape))
return FALSE;
-/* -------------------------------------------------------------------- */
-/* Assign value, marking record as dirty if it changes. */
-/* -------------------------------------------------------------------- */
- if( bIsDeleted )
+ /* -------------------------------------------------------------------- */
+ /* Assign value, marking record as dirty if it changes. */
+ /* -------------------------------------------------------------------- */
+ char chNewFlag;
+ if (bIsDeleted)
chNewFlag = '*';
else
chNewFlag = ' ';
- if( psDBF->pszCurrentRecord[0] != chNewFlag )
+ if (psDBF->pszCurrentRecord[0] != chNewFlag)
{
psDBF->bCurrentRecordModified = TRUE;
psDBF->bUpdated = TRUE;
/* DBFGetCodePage */
/************************************************************************/
-const char SHPAPI_CALL1(*)
-DBFGetCodePage(DBFHandle psDBF )
+const char SHPAPI_CALL1(*) DBFGetCodePage(DBFHandle psDBF)
{
- if( psDBF == SHPLIB_NULLPTR )
+ if (psDBF == SHPLIB_NULLPTR)
return SHPLIB_NULLPTR;
return psDBF->pszCodePage;
}
/* Remove a field from a .dbf file */
/************************************************************************/
-int SHPAPI_CALL
-DBFDeleteField(DBFHandle psDBF, int iField)
+int SHPAPI_CALL DBFDeleteField(DBFHandle psDBF, int iField)
{
- int nOldRecordLength, nOldHeaderLength;
- int nDeletedFieldOffset, nDeletedFieldSize;
- SAOffset nRecordOffset;
- char* pszRecord;
- int i, iRecord;
-
if (iField < 0 || iField >= psDBF->nFields)
return FALSE;
/* make sure that everything is written in .dbf */
- if( !DBFFlushRecord( psDBF ) )
+ if (!DBFFlushRecord(psDBF))
return FALSE;
/* get information about field to be deleted */
- nOldRecordLength = psDBF->nRecordLength;
- nOldHeaderLength = psDBF->nHeaderLength;
- nDeletedFieldOffset = psDBF->panFieldOffset[iField];
- nDeletedFieldSize = psDBF->panFieldSize[iField];
+ int nOldRecordLength = psDBF->nRecordLength;
+ int nOldHeaderLength = psDBF->nHeaderLength;
+ int nDeletedFieldOffset = psDBF->panFieldOffset[iField];
+ int nDeletedFieldSize = psDBF->panFieldSize[iField];
/* update fields info */
- for (i = iField + 1; i < psDBF->nFields; i++)
+ for (int i = iField + 1; i < psDBF->nFields; i++)
{
- psDBF->panFieldOffset[i-1] = psDBF->panFieldOffset[i] - nDeletedFieldSize;
- psDBF->panFieldSize[i-1] = psDBF->panFieldSize[i];
- psDBF->panFieldDecimals[i-1] = psDBF->panFieldDecimals[i];
- psDBF->pachFieldType[i-1] = psDBF->pachFieldType[i];
+ psDBF->panFieldOffset[i - 1] =
+ psDBF->panFieldOffset[i] - nDeletedFieldSize;
+ psDBF->panFieldSize[i - 1] = psDBF->panFieldSize[i];
+ psDBF->panFieldDecimals[i - 1] = psDBF->panFieldDecimals[i];
+ psDBF->pachFieldType[i - 1] = psDBF->pachFieldType[i];
}
/* resize fields arrays */
psDBF->nFields--;
- psDBF->panFieldOffset = STATIC_CAST(int *,
- SfRealloc( psDBF->panFieldOffset, sizeof(int) * psDBF->nFields ));
+ psDBF->panFieldOffset = STATIC_CAST(
+ int *, realloc(psDBF->panFieldOffset, sizeof(int) * psDBF->nFields));
- psDBF->panFieldSize = STATIC_CAST(int *,
- SfRealloc( psDBF->panFieldSize, sizeof(int) * psDBF->nFields ));
+ psDBF->panFieldSize = STATIC_CAST(
+ int *, realloc(psDBF->panFieldSize, sizeof(int) * psDBF->nFields));
- psDBF->panFieldDecimals = STATIC_CAST(int *,
- SfRealloc( psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields ));
+ psDBF->panFieldDecimals = STATIC_CAST(
+ int *, realloc(psDBF->panFieldDecimals, sizeof(int) * psDBF->nFields));
- psDBF->pachFieldType = STATIC_CAST(char *,
- SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields ));
+ psDBF->pachFieldType = STATIC_CAST(
+ char *, realloc(psDBF->pachFieldType, sizeof(char) * psDBF->nFields));
/* update header information */
psDBF->nHeaderLength -= XBASE_FLDHDR_SZ;
psDBF->nRecordLength -= nDeletedFieldSize;
/* overwrite field information in header */
- memmove(psDBF->pszHeader + iField*XBASE_FLDHDR_SZ,
- psDBF->pszHeader + (iField+1)*XBASE_FLDHDR_SZ,
- sizeof(char) * (psDBF->nFields - iField)*XBASE_FLDHDR_SZ);
+ memmove(psDBF->pszHeader + iField * XBASE_FLDHDR_SZ,
+ psDBF->pszHeader + (iField + 1) * XBASE_FLDHDR_SZ,
+ sizeof(char) * (psDBF->nFields - iField) * XBASE_FLDHDR_SZ);
- psDBF->pszHeader = STATIC_CAST(char *, SfRealloc(psDBF->pszHeader,
- psDBF->nFields*XBASE_FLDHDR_SZ));
+ psDBF->pszHeader = STATIC_CAST(
+ char *, realloc(psDBF->pszHeader, psDBF->nFields * XBASE_FLDHDR_SZ));
/* update size of current record appropriately */
- psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
- psDBF->nRecordLength));
+ psDBF->pszCurrentRecord = STATIC_CAST(
+ char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));
/* we're done if we're dealing with not yet created .dbf */
- if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
+ if (psDBF->bNoHeader && psDBF->nRecords == 0)
return TRUE;
/* force update of header with new header and record length */
psDBF->bNoHeader = TRUE;
- DBFUpdateHeader( psDBF );
+ DBFUpdateHeader(psDBF);
/* alloc record */
- pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
+ char *pszRecord =
+ STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
/* shift records to their new positions */
- for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+ for (int iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
{
- nRecordOffset =
- nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + nOldHeaderLength;
+ SAOffset nRecordOffset =
+ nOldRecordLength * STATIC_CAST(SAOffset, iRecord) +
+ nOldHeaderLength;
/* load record */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ if (psDBF->sHooks.FRead(pszRecord, nOldRecordLength, 1, psDBF->fp) != 1)
+ {
+ free(pszRecord);
+ return FALSE;
+ }
- nRecordOffset =
- psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+ nRecordOffset = psDBF->nRecordLength * STATIC_CAST(SAOffset, iRecord) +
+ psDBF->nHeaderLength;
/* move record in two steps */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FWrite( pszRecord, nDeletedFieldOffset, 1, psDBF->fp );
- psDBF->sHooks.FWrite( pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
- nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize,
- 1, psDBF->fp );
-
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ psDBF->sHooks.FWrite(pszRecord, nDeletedFieldOffset, 1, psDBF->fp);
+ psDBF->sHooks.FWrite(
+ pszRecord + nDeletedFieldOffset + nDeletedFieldSize,
+ nOldRecordLength - nDeletedFieldOffset - nDeletedFieldSize, 1,
+ psDBF->fp);
}
- if( psDBF->bWriteEndOfFileChar )
+ if (psDBF->bWriteEndOfFileChar)
{
char ch = END_OF_FILE_CHARACTER;
SAOffset nEOFOffset =
- psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
+ psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nRecords) +
+ psDBF->nHeaderLength;
- psDBF->sHooks.FSeek( psDBF->fp, nEOFOffset, 0 );
- psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nEOFOffset, 0);
+ psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
}
/* TODO: truncate file */
/* code of DBFReorderFields. */
/************************************************************************/
-int SHPAPI_CALL
-DBFReorderFields( DBFHandle psDBF, int* panMap )
+int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap)
{
- SAOffset nRecordOffset;
- int i, iRecord;
- int *panFieldOffsetNew;
- int *panFieldSizeNew;
- int *panFieldDecimalsNew;
- char *pachFieldTypeNew;
- char *pszHeaderNew;
- char *pszRecord;
- char *pszRecordNew;
-
- if ( psDBF->nFields == 0 )
+ if (psDBF->nFields == 0)
return TRUE;
/* make sure that everything is written in .dbf */
- if( !DBFFlushRecord( psDBF ) )
+ if (!DBFFlushRecord(psDBF))
return FALSE;
- /* a simple malloc() would be enough, but calloc() helps clang static analyzer */
- panFieldOffsetNew = STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
- panFieldSizeNew = STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
- panFieldDecimalsNew = STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
- pachFieldTypeNew = STATIC_CAST(char *, calloc(sizeof(char), psDBF->nFields));
- pszHeaderNew = STATIC_CAST(char*, malloc(sizeof(char) * XBASE_FLDHDR_SZ *
- psDBF->nFields));
+ /* a simple malloc() would be enough, but calloc() helps clang static
+ * analyzer */
+ int *panFieldOffsetNew =
+ STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+ int *panFieldSizeNew =
+ STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+ int *panFieldDecimalsNew =
+ STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+ char *pachFieldTypeNew =
+ STATIC_CAST(char *, calloc(sizeof(char), psDBF->nFields));
+ char *pszHeaderNew = STATIC_CAST(
+ char *, malloc(sizeof(char) * XBASE_FLDHDR_SZ * psDBF->nFields));
/* shuffle fields definitions */
- for(i=0; i < psDBF->nFields; i++)
+ for (int i = 0; i < psDBF->nFields; i++)
{
panFieldSizeNew[i] = psDBF->panFieldSize[panMap[i]];
panFieldDecimalsNew[i] = psDBF->panFieldDecimals[panMap[i]];
psDBF->pszHeader + panMap[i] * XBASE_FLDHDR_SZ, XBASE_FLDHDR_SZ);
}
panFieldOffsetNew[0] = 1;
- for(i=1; i < psDBF->nFields; i++)
+ for (int i = 1; i < psDBF->nFields; i++)
{
- panFieldOffsetNew[i] = panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
+ panFieldOffsetNew[i] =
+ panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
}
free(psDBF->pszHeader);
psDBF->pszHeader = pszHeaderNew;
+ bool errorAbort = false;
+
/* we're done if we're dealing with not yet created .dbf */
- if ( !(psDBF->bNoHeader && psDBF->nRecords == 0) )
+ if (!(psDBF->bNoHeader && psDBF->nRecords == 0))
{
/* force update of header with new header and record length */
psDBF->bNoHeader = TRUE;
- DBFUpdateHeader( psDBF );
+ DBFUpdateHeader(psDBF);
/* alloc record */
- pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
- pszRecordNew = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+ char *pszRecord =
+ STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+ char *pszRecordNew =
+ STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
/* shuffle fields in records */
- for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+ for (int iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
{
- nRecordOffset =
- psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+ const SAOffset nRecordOffset =
+ psDBF->nRecordLength * STATIC_CAST(SAOffset, iRecord) +
+ psDBF->nHeaderLength;
/* load record */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FRead( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ if (psDBF->sHooks.FRead(pszRecord, psDBF->nRecordLength, 1,
+ psDBF->fp) != 1)
+ {
+ errorAbort = true;
+ break;
+ }
pszRecordNew[0] = pszRecord[0];
- for(i=0; i < psDBF->nFields; i++)
+ for (int i = 0; i < psDBF->nFields; i++)
{
memcpy(pszRecordNew + panFieldOffsetNew[i],
pszRecord + psDBF->panFieldOffset[panMap[i]],
}
/* write record */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FWrite( pszRecordNew, psDBF->nRecordLength, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ psDBF->sHooks.FWrite(pszRecordNew, psDBF->nRecordLength, 1,
+ psDBF->fp);
}
/* free record */
free(pszRecordNew);
}
+ if (errorAbort)
+ {
+ free(panFieldOffsetNew);
+ free(panFieldSizeNew);
+ free(panFieldDecimalsNew);
+ free(pachFieldTypeNew);
+ psDBF->nCurrentRecord = -1;
+ psDBF->bCurrentRecordModified = FALSE;
+ psDBF->bUpdated = FALSE;
+ return FALSE;
+ }
+
free(psDBF->panFieldOffset);
free(psDBF->panFieldSize);
free(psDBF->panFieldDecimals);
psDBF->panFieldOffset = panFieldOffsetNew;
psDBF->panFieldSize = panFieldSizeNew;
- psDBF->panFieldDecimals =panFieldDecimalsNew;
+ psDBF->panFieldDecimals = panFieldDecimalsNew;
psDBF->pachFieldType = pachFieldTypeNew;
psDBF->nCurrentRecord = -1;
return TRUE;
}
-
/************************************************************************/
/* DBFAlterFieldDefn() */
/* */
/* Alter a field definition in a .dbf file */
/************************************************************************/
-int SHPAPI_CALL
-DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
- char chType, int nWidth, int nDecimals )
+int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
+ const char *pszFieldName, char chType,
+ int nWidth, int nDecimals)
{
- int i;
- int iRecord;
- int nOffset;
- int nOldWidth;
- int nOldRecordLength;
- SAOffset nRecordOffset;
- char* pszFInfo;
- char chOldType;
- int bIsNULL;
- char chFieldFill;
-
if (iField < 0 || iField >= psDBF->nFields)
return FALSE;
/* make sure that everything is written in .dbf */
- if( !DBFFlushRecord( psDBF ) )
+ if (!DBFFlushRecord(psDBF))
return FALSE;
- chFieldFill = DBFGetNullCharacter(chType);
+ const char chFieldFill = DBFGetNullCharacter(chType);
- chOldType = psDBF->pachFieldType[iField];
- nOffset = psDBF->panFieldOffset[iField];
- nOldWidth = psDBF->panFieldSize[iField];
- nOldRecordLength = psDBF->nRecordLength;
+ const char chOldType = psDBF->pachFieldType[iField];
+ const int nOffset = psDBF->panFieldOffset[iField];
+ const int nOldWidth = psDBF->panFieldSize[iField];
+ const int nOldRecordLength = psDBF->nRecordLength;
-/* -------------------------------------------------------------------- */
-/* Do some checking to ensure we can add records to this file. */
-/* -------------------------------------------------------------------- */
- if( nWidth < 1 )
+ /* -------------------------------------------------------------------- */
+ /* Do some checking to ensure we can add records to this file. */
+ /* -------------------------------------------------------------------- */
+ if (nWidth < 1)
return -1;
- if( nWidth > XBASE_FLD_MAX_WIDTH )
+ if (nWidth > XBASE_FLD_MAX_WIDTH)
nWidth = XBASE_FLD_MAX_WIDTH;
-/* -------------------------------------------------------------------- */
-/* Assign the new field information fields. */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* Assign the new field information fields. */
+ /* -------------------------------------------------------------------- */
psDBF->panFieldSize[iField] = nWidth;
psDBF->panFieldDecimals[iField] = nDecimals;
psDBF->pachFieldType[iField] = chType;
-/* -------------------------------------------------------------------- */
-/* Update the header information. */
-/* -------------------------------------------------------------------- */
- pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * iField;
+ /* -------------------------------------------------------------------- */
+ /* Update the header information. */
+ /* -------------------------------------------------------------------- */
+ char *pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * iField;
- for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
+ for (int i = 0; i < XBASE_FLDHDR_SZ; i++)
pszFInfo[i] = '\0';
- strncpy( pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE );
+ strncpy(pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE);
pszFInfo[11] = psDBF->pachFieldType[iField];
- if( chType == 'C' )
+ if (chType == 'C')
{
pszFInfo[16] = STATIC_CAST(unsigned char, nWidth % 256);
pszFInfo[17] = STATIC_CAST(unsigned char, nWidth / 256);
pszFInfo[17] = STATIC_CAST(unsigned char, nDecimals);
}
-/* -------------------------------------------------------------------- */
-/* Update offsets */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* Update offsets */
+ /* -------------------------------------------------------------------- */
if (nWidth != nOldWidth)
{
- for (i = iField + 1; i < psDBF->nFields; i++)
- psDBF->panFieldOffset[i] += nWidth - nOldWidth;
+ for (int i = iField + 1; i < psDBF->nFields; i++)
+ psDBF->panFieldOffset[i] += nWidth - nOldWidth;
psDBF->nRecordLength += nWidth - nOldWidth;
- psDBF->pszCurrentRecord = STATIC_CAST(char *, SfRealloc(psDBF->pszCurrentRecord,
- psDBF->nRecordLength));
+ psDBF->pszCurrentRecord = STATIC_CAST(
+ char *, realloc(psDBF->pszCurrentRecord, psDBF->nRecordLength));
}
/* we're done if we're dealing with not yet created .dbf */
- if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
+ if (psDBF->bNoHeader && psDBF->nRecords == 0)
return TRUE;
/* force update of header with new header and record length */
psDBF->bNoHeader = TRUE;
- DBFUpdateHeader( psDBF );
+ DBFUpdateHeader(psDBF);
+
+ bool errorAbort = false;
if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
{
- char* pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
- char* pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
+ char *pszRecord =
+ STATIC_CAST(char *, malloc(sizeof(char) * nOldRecordLength));
+ char *pszOldField =
+ STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
/* cppcheck-suppress uninitdata */
pszOldField[nOldWidth] = 0;
/* move records to their new positions */
- for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+ for (int iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
{
- nRecordOffset =
- nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+ SAOffset nRecordOffset =
+ nOldRecordLength * STATIC_CAST(SAOffset, iRecord) +
+ psDBF->nHeaderLength;
/* load record */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ if (psDBF->sHooks.FRead(pszRecord, nOldRecordLength, 1,
+ psDBF->fp) != 1)
+ {
+ errorAbort = true;
+ break;
+ }
memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
- bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
+ const bool bIsNULL = DBFIsValueNULL(chOldType, pszOldField);
if (nWidth != nOldWidth)
{
- if ((chOldType == 'N' || chOldType == 'F' || chOldType == 'D') && pszOldField[0] == ' ')
+ if ((chOldType == 'N' || chOldType == 'F' ||
+ chOldType == 'D') &&
+ pszOldField[0] == ' ')
{
/* Strip leading spaces when truncating a numeric field */
- memmove( pszRecord + nOffset,
- pszRecord + nOffset + nOldWidth - nWidth,
- nWidth );
+ memmove(pszRecord + nOffset,
+ pszRecord + nOffset + nOldWidth - nWidth, nWidth);
}
if (nOffset + nOldWidth < nOldRecordLength)
{
- memmove( pszRecord + nOffset + nWidth,
+ memmove(pszRecord + nOffset + nWidth,
pszRecord + nOffset + nOldWidth,
nOldRecordLength - (nOffset + nOldWidth));
}
/* Convert null value to the appropriate value of the new type */
if (bIsNULL)
{
- memset( pszRecord + nOffset, chFieldFill, nWidth);
+ memset(pszRecord + nOffset, chFieldFill, nWidth);
}
nRecordOffset =
- psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+ psDBF->nRecordLength * STATIC_CAST(SAOffset, iRecord) +
+ psDBF->nHeaderLength;
/* write record */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ psDBF->sHooks.FWrite(pszRecord, psDBF->nRecordLength, 1, psDBF->fp);
}
- if( psDBF->bWriteEndOfFileChar )
+ if (!errorAbort && psDBF->bWriteEndOfFileChar)
{
char ch = END_OF_FILE_CHARACTER;
- nRecordOffset =
- psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
+ SAOffset nRecordOffset =
+ psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nRecords) +
+ psDBF->nHeaderLength;
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
}
/* TODO: truncate file */
}
else if (nWidth > nOldWidth)
{
- char* pszRecord = STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
- char* pszOldField = STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
+ char *pszRecord =
+ STATIC_CAST(char *, malloc(sizeof(char) * psDBF->nRecordLength));
+ char *pszOldField =
+ STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
/* cppcheck-suppress uninitdata */
pszOldField[nOldWidth] = 0;
/* move records to their new positions */
- for (iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
+ for (int iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
{
- nRecordOffset =
- nOldRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+ SAOffset nRecordOffset =
+ nOldRecordLength * STATIC_CAST(SAOffset, iRecord) +
+ psDBF->nHeaderLength;
/* load record */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ if (psDBF->sHooks.FRead(pszRecord, nOldRecordLength, 1,
+ psDBF->fp) != 1)
+ {
+ errorAbort = true;
+ break;
+ }
memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
- bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
+ const bool bIsNULL = DBFIsValueNULL(chOldType, pszOldField);
if (nOffset + nOldWidth < nOldRecordLength)
{
- memmove( pszRecord + nOffset + nWidth,
- pszRecord + nOffset + nOldWidth,
- nOldRecordLength - (nOffset + nOldWidth));
+ memmove(pszRecord + nOffset + nWidth,
+ pszRecord + nOffset + nOldWidth,
+ nOldRecordLength - (nOffset + nOldWidth));
}
/* Convert null value to the appropriate value of the new type */
if (bIsNULL)
{
- memset( pszRecord + nOffset, chFieldFill, nWidth);
+ memset(pszRecord + nOffset, chFieldFill, nWidth);
}
else
{
if ((chOldType == 'N' || chOldType == 'F'))
{
/* Add leading spaces when expanding a numeric field */
- memmove( pszRecord + nOffset + nWidth - nOldWidth,
- pszRecord + nOffset, nOldWidth );
- memset( pszRecord + nOffset, ' ', nWidth - nOldWidth );
+ memmove(pszRecord + nOffset + nWidth - nOldWidth,
+ pszRecord + nOffset, nOldWidth);
+ memset(pszRecord + nOffset, ' ', nWidth - nOldWidth);
}
else
{
/* Add trailing spaces */
- memset(pszRecord + nOffset + nOldWidth, ' ', nWidth - nOldWidth);
+ memset(pszRecord + nOffset + nOldWidth, ' ',
+ nWidth - nOldWidth);
}
}
nRecordOffset =
- psDBF->nRecordLength * STATIC_CAST(SAOffset,iRecord) + psDBF->nHeaderLength;
+ psDBF->nRecordLength * STATIC_CAST(SAOffset, iRecord) +
+ psDBF->nHeaderLength;
/* write record */
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ psDBF->sHooks.FWrite(pszRecord, psDBF->nRecordLength, 1, psDBF->fp);
}
- if( psDBF->bWriteEndOfFileChar )
+ if (!errorAbort && psDBF->bWriteEndOfFileChar)
{
char ch = END_OF_FILE_CHARACTER;
- nRecordOffset =
- psDBF->nRecordLength * STATIC_CAST(SAOffset,psDBF->nRecords) + psDBF->nHeaderLength;
+ SAOffset nRecordOffset =
+ psDBF->nRecordLength * STATIC_CAST(SAOffset, psDBF->nRecords) +
+ psDBF->nHeaderLength;
- psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
- psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+ psDBF->sHooks.FSeek(psDBF->fp, nRecordOffset, 0);
+ psDBF->sHooks.FWrite(&ch, 1, 1, psDBF->fp);
}
free(pszRecord);
free(pszOldField);
}
+ if (errorAbort)
+ {
+ psDBF->nCurrentRecord = -1;
+ psDBF->bCurrentRecordModified = TRUE;
+ psDBF->bUpdated = FALSE;
+
+ return FALSE;
+ }
psDBF->nCurrentRecord = -1;
psDBF->bCurrentRecordModified = FALSE;
psDBF->bUpdated = TRUE;
/* DBFSetWriteEndOfFileChar() */
/************************************************************************/
-void SHPAPI_CALL DBFSetWriteEndOfFileChar( DBFHandle psDBF, int bWriteFlag )
+void SHPAPI_CALL DBFSetWriteEndOfFileChar(DBFHandle psDBF, int bWriteFlag)
{
psDBF->bWriteEndOfFileChar = bWriteFlag;
}
/******************************************************************************
- * $Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $
*
* Project: Shapelib
* Purpose: Default implementation of file io based on stdio.
******************************************************************************
* Copyright (c) 2007, Frank Warmerdam
*
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see COPYING). This
- * option is discussed in more detail in shapelib.html.
- *
- * --
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
******************************************************************************
*
- * $Log: safileio.c,v $
- * Revision 1.6 2018-06-15 19:56:32 erouault
- * * safileio.c: remove duplicate test. Patch by Jaroslav Fojtik.
- * Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2744
- *
- * Revision 1.5 2016-12-05 12:44:05 erouault
- * * Major overhaul of Makefile build system to use autoconf/automake.
- *
- * * Warning fixes in contrib/
- *
- * Revision 1.4 2008-01-16 20:05:14 bram
- * Add file hooks that accept UTF-8 encoded filenames on some platforms. Use SASetupUtf8Hooks
- * tosetup the hooks and check SHPAPI_UTF8_HOOKS for its availability. Currently, this
- * is only available on the Windows platform that decodes the UTF-8 filenames to wide
- * character strings and feeds them to _wfopen and _wremove.
- *
- * Revision 1.3 2007/12/18 18:28:11 bram
- * - create hook for client specific atof (bugzilla ticket 1615)
- * - check for NULL handle before closing cpCPG file, and close after reading.
- *
- * Revision 1.2 2007/12/15 20:25:30 bram
- * dbfopen.c now reads the Code Page information from the DBF file, and exports
- * this information as a string through the DBFGetCodePage function. This is
- * either the number from the LDID header field ("LDID/<number>") or as the
- * content of an accompanying .CPG file. When creating a DBF file, the code can
- * be set using DBFCreateEx.
- *
- * Revision 1.1 2007/12/06 06:56:41 fwarmerdam
- * new
- *
*/
#include "shapefil.h"
+#include <assert.h>
#include <math.h>
#include <limits.h>
-#include <assert.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
-
-SHP_CVSID("$Id: safileio.c,v 1.6 2018-06-15 19:56:32 erouault Exp $");
#ifdef SHPAPI_UTF8_HOOKS
-# ifdef SHPAPI_WINDOWS
-# define WIN32_LEAN_AND_MEAN
-# define NOMINMAX
-# include <windows.h>
-# pragma comment(lib, "kernel32.lib")
-# endif
+#ifdef SHPAPI_WINDOWS
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include <windows.h>
+#pragma comment(lib, "kernel32.lib")
+#endif
#endif
-/************************************************************************/
-/* SADFOpen() */
-/************************************************************************/
-
-SAFile SADFOpen( const char *pszFilename, const char *pszAccess )
-
+static SAFile SADFOpen(const char *pszFilename, const char *pszAccess,
+ void *pvUserData)
{
- return (SAFile) fopen( pszFilename, pszAccess );
+ (void)pvUserData;
+ return (SAFile)fopen(pszFilename, pszAccess);
}
-/************************************************************************/
-/* SADFRead() */
-/************************************************************************/
-
-SAOffset SADFRead( void *p, SAOffset size, SAOffset nmemb, SAFile file )
-
+static SAOffset SADFRead(void *p, SAOffset size, SAOffset nmemb, SAFile file)
{
- return (SAOffset) fread( p, (size_t) size, (size_t) nmemb,
- (FILE *) file );
+ return (SAOffset)fread(p, (size_t)size, (size_t)nmemb, (FILE *)file);
}
-/************************************************************************/
-/* SADFWrite() */
-/************************************************************************/
-
-SAOffset SADFWrite( void *p, SAOffset size, SAOffset nmemb, SAFile file )
-
+static SAOffset SADFWrite(const void *p, SAOffset size, SAOffset nmemb,
+ SAFile file)
{
- return (SAOffset) fwrite( p, (size_t) size, (size_t) nmemb,
- (FILE *) file );
+ return (SAOffset)fwrite(p, (size_t)size, (size_t)nmemb, (FILE *)file);
}
-/************************************************************************/
-/* SADFSeek() */
-/************************************************************************/
-
-SAOffset SADFSeek( SAFile file, SAOffset offset, int whence )
-
+static SAOffset SADFSeek(SAFile file, SAOffset offset, int whence)
{
- return (SAOffset) fseek( (FILE *) file, (long) offset, whence );
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ return (SAOffset)_fseeki64((FILE *)file, (__int64)offset, whence);
+#else
+ return (SAOffset)fseek((FILE *)file, (long)offset, whence);
+#endif
}
-/************************************************************************/
-/* SADFTell() */
-/************************************************************************/
-
-SAOffset SADFTell( SAFile file )
-
+static SAOffset SADFTell(SAFile file)
{
- return (SAOffset) ftell( (FILE *) file );
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ return (SAOffset)_ftelli64((FILE *)file);
+#else
+ return (SAOffset)ftell((FILE *)file);
+#endif
}
-/************************************************************************/
-/* SADFFlush() */
-/************************************************************************/
-
-int SADFFlush( SAFile file )
-
+static int SADFFlush(SAFile file)
{
- return fflush( (FILE *) file );
+ return fflush((FILE *)file);
}
-/************************************************************************/
-/* SADFClose() */
-/************************************************************************/
-
-int SADFClose( SAFile file )
-
+static int SADFClose(SAFile file)
{
- return fclose( (FILE *) file );
+ return fclose((FILE *)file);
}
-/************************************************************************/
-/* SADFClose() */
-/************************************************************************/
-
-int SADRemove( const char *filename )
-
+static int SADRemove(const char *filename, void *pvUserData)
{
- return remove( filename );
+ (void)pvUserData;
+ return remove(filename);
}
-/************************************************************************/
-/* SADError() */
-/************************************************************************/
-
-void SADError( const char *message )
-
+static void SADError(const char *message)
{
- fprintf( stderr, "%s\n", message );
+ fprintf(stderr, "%s\n", message);
}
-/************************************************************************/
-/* SASetupDefaultHooks() */
-/************************************************************************/
-
-void SASetupDefaultHooks( SAHooks *psHooks )
-
+void SASetupDefaultHooks(SAHooks *psHooks)
{
- psHooks->FOpen = SADFOpen;
- psHooks->FRead = SADFRead;
- psHooks->FWrite = SADFWrite;
- psHooks->FSeek = SADFSeek;
- psHooks->FTell = SADFTell;
- psHooks->FFlush = SADFFlush;
- psHooks->FClose = SADFClose;
- psHooks->Remove = SADRemove;
-
- psHooks->Error = SADError;
- psHooks->Atof = atof;
+ psHooks->FOpen = SADFOpen;
+ psHooks->FRead = SADFRead;
+ psHooks->FWrite = SADFWrite;
+ psHooks->FSeek = SADFSeek;
+ psHooks->FTell = SADFTell;
+ psHooks->FFlush = SADFFlush;
+ psHooks->FClose = SADFClose;
+ psHooks->Remove = SADRemove;
+
+ psHooks->Error = SADError;
+ psHooks->Atof = atof;
+ psHooks->pvUserData = NULL;
}
-
-
-
#ifdef SHPAPI_WINDOWS
-/************************************************************************/
-/* Utf8ToWideChar */
-/************************************************************************/
-
-const wchar_t* Utf8ToWideChar( const char *pszFilename )
+static wchar_t *Utf8ToWideChar(const char *pszFilename)
{
- int nMulti, nWide;
- wchar_t *pwszFileName;
-
- nMulti = strlen(pszFilename) + 1;
- nWide = MultiByteToWideChar( CP_UTF8, 0, pszFilename, nMulti, 0, 0);
- if( nWide == 0 )
+ const int nMulti = (int)strlen(pszFilename) + 1;
+ const int nWide =
+ MultiByteToWideChar(CP_UTF8, 0, pszFilename, nMulti, 0, 0);
+ if (nWide == 0)
{
return NULL;
}
- pwszFileName = (wchar_t*) malloc(nWide * sizeof(wchar_t));
- if ( pwszFileName == NULL )
+ wchar_t *pwszFileName = (wchar_t *)malloc(nWide * sizeof(wchar_t));
+ if (pwszFileName == NULL)
{
return NULL;
}
- if( MultiByteToWideChar( CP_UTF8, 0, pszFilename, nMulti, pwszFileName, nWide ) == 0 )
+ if (MultiByteToWideChar(CP_UTF8, 0, pszFilename, nMulti, pwszFileName,
+ nWide) == 0)
{
- free( pwszFileName );
+ free(pwszFileName);
return NULL;
}
return pwszFileName;
/* SAUtf8WFOpen */
/************************************************************************/
-SAFile SAUtf8WFOpen( const char *pszFilename, const char *pszAccess )
+SAFile SAUtf8WFOpen(const char *pszFilename, const char *pszAccess)
{
SAFile file = NULL;
- const wchar_t *pwszFileName, *pwszAccess;
- pwszFileName = Utf8ToWideChar( pszFilename );
- pwszAccess = Utf8ToWideChar( pszAccess );
- if( pwszFileName != NULL && pwszAccess != NULL)
+ wchar_t *pwszFileName = Utf8ToWideChar(pszFilename);
+ wchar_t *pwszAccess = Utf8ToWideChar(pszAccess);
+ if (pwszFileName != NULL && pwszAccess != NULL)
{
- file = (SAFile) _wfopen( pwszFileName, pwszAccess );
+ file = (SAFile)_wfopen(pwszFileName, pwszAccess);
}
- free ((wchar_t*) pwszFileName);
- free ((wchar_t*) pwszAccess);
+ free(pwszFileName);
+ free(pwszAccess);
return file;
}
-/************************************************************************/
-/* SAUtf8WRemove() */
-/************************************************************************/
-
-int SAUtf8WRemove( const char *pszFilename )
+int SAUtf8WRemove(const char *pszFilename)
{
- const wchar_t *pwszFileName = Utf8ToWideChar( pszFilename );
- int rc = -1;
- if( pwszFileName != NULL )
+ wchar_t *pwszFileName = Utf8ToWideChar(pszFilename);
+ int rc = -1;
+ if (pwszFileName != NULL)
{
- rc = _wremove( pwszFileName );
+ rc = _wremove(pwszFileName);
}
- free ((wchar_t*) pwszFileName);
+ free(pwszFileName);
return rc;
}
#endif
#ifdef SHPAPI_UTF8_HOOKS
-
-/************************************************************************/
-/* SASetupUtf8Hooks() */
-/************************************************************************/
-
-void SASetupUtf8Hooks( SAHooks *psHooks )
-{
-#ifdef SHPAPI_WINDOWS
- psHooks->FOpen = SAUtf8WFOpen;
- psHooks->Remove = SAUtf8WRemove;
-#else
-# error "no implementations of UTF-8 hooks available for this platform"
+#ifndef SHPAPI_WINDOWS
+#error "no implementations of UTF-8 hooks available for this platform"
#endif
- psHooks->FRead = SADFRead;
- psHooks->FWrite = SADFWrite;
- psHooks->FSeek = SADFSeek;
- psHooks->FTell = SADFTell;
- psHooks->FFlush = SADFFlush;
- psHooks->FClose = SADFClose;
- psHooks->Error = SADError;
- psHooks->Atof = atof;
+void SASetupUtf8Hooks(SAHooks *psHooks)
+{
+ psHooks->FOpen = SAUtf8WFOpen;
+ psHooks->Remove = SAUtf8WRemove;
+ psHooks->FRead = SADFRead;
+ psHooks->FWrite = SADFWrite;
+ psHooks->FSeek = SADFSeek;
+ psHooks->FTell = SADFTell;
+ psHooks->FFlush = SADFFlush;
+ psHooks->FClose = SADFClose;
+
+ psHooks->Error = SADError;
+ psHooks->Atof = atof;
}
-
#endif
#define SHAPEFILE_H_INCLUDED
/******************************************************************************
- * $Id: shapefil.h,v 1.56 2018-08-16 15:39:07 erouault Exp $
*
* Project: Shapelib
* Purpose: Primary include file for Shapelib.
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
- * Copyright (c) 2012-2016, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2012-2016, Even Rouault <even dot rouault at spatialys.com>
*
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see COPYING). This
- * option is discussed in more detail in shapelib.html.
- *
- * --
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
******************************************************************************
*
- * $Log: shapefil.h,v $
- * Revision 1.56 2018-08-16 15:39:07 erouault
- * * shpopen.c, dbfopen.c, shptree.c, sbnsearch.c: resyc with GDAL
- * internal shapelib. Mostly to allow building those files as C++
- * without warning. Also add FTDate entry in DBFFieldType
- * (see https://github.com/OSGeo/gdal/pull/308). And some other
- * code cleanups
- *
- * Revision 1.55 2016-12-05 18:44:08 erouault
- * * dbfopen.c, shapefil.h: write DBF end-of-file character 0x1A by default.
- * This behaviour can be controlled with the DBFSetWriteEndOfFileChar()
- * function.
- *
- * Revision 1.54 2016-12-05 12:44:05 erouault
- * * Major overhaul of Makefile build system to use autoconf/automake.
- *
- * * Warning fixes in contrib/
- *
- * Revision 1.53 2016-12-04 15:30:15 erouault
- * * shpopen.c, dbfopen.c, shptree.c, shapefil.h: resync with
- * GDAL Shapefile driver. Mostly cleanups. SHPObject and DBFInfo
- * structures extended with new members. New functions:
- * DBFSetLastModifiedDate, SHPOpenLLEx, SHPRestoreSHX,
- * SHPSetFastModeReadObject
- *
- * * sbnsearch.c: new file to implement original ESRI .sbn spatial
- * index reading. (no write support). New functions:
- * SBNOpenDiskTree, SBNCloseDiskTree, SBNSearchDiskTree,
- * SBNSearchDiskTreeInteger, SBNSearchFreeIds
- *
- * * Makefile, makefile.vc, CMakeLists.txt, shapelib.def: updates
- * with new file and symbols.
- *
- * * commit: helper script to cvs commit
- *
- * Revision 1.52 2011-12-11 22:26:46 fwarmerdam
- * upgrade .qix access code to use SAHooks (gdal #3365)
- *
- * Revision 1.51 2011-07-24 05:59:25 fwarmerdam
- * minimize use of CPLError in favor of SAHooks.Error()
- *
- * Revision 1.50 2011-05-13 17:35:17 fwarmerdam
- * added DBFReorderFields() and DBFAlterFields() functions (from Even)
- *
- * Revision 1.49 2011-04-16 14:38:21 fwarmerdam
- * avoid warnings with gcc on SHP_CVSID
- *
- * Revision 1.48 2010-08-27 23:42:52 fwarmerdam
- * add SHPAPI_CALL attribute in code
- *
- * Revision 1.47 2010-01-28 11:34:34 fwarmerdam
- * handle the shape file length limits more gracefully (#3236)
- *
- * Revision 1.46 2008-11-12 14:28:15 fwarmerdam
- * DBFCreateField() now works on files with records
- *
- * Revision 1.45 2008/11/11 17:47:10 fwarmerdam
- * added DBFDeleteField() function
- *
- * Revision 1.44 2008/01/16 20:05:19 bram
- * Add file hooks that accept UTF-8 encoded filenames on some platforms. Use SASetupUtf8Hooks
- * tosetup the hooks and check SHPAPI_UTF8_HOOKS for its availability. Currently, this
- * is only available on the Windows platform that decodes the UTF-8 filenames to wide
- * character strings and feeds them to _wfopen and _wremove.
- *
- * Revision 1.43 2008/01/10 16:35:30 fwarmerdam
- * avoid _ prefix on #defined symbols (bug 1840)
- *
- * Revision 1.42 2007/12/18 18:28:14 bram
- * - create hook for client specific atof (bugzilla ticket 1615)
- * - check for NULL handle before closing cpCPG file, and close after reading.
- *
- * Revision 1.41 2007/12/15 20:25:32 bram
- * dbfopen.c now reads the Code Page information from the DBF file, and exports
- * this information as a string through the DBFGetCodePage function. This is
- * either the number from the LDID header field ("LDID/<number>") or as the
- * content of an accompanying .CPG file. When creating a DBF file, the code can
- * be set using DBFCreateEx.
- *
- * Revision 1.40 2007/12/06 07:00:25 fwarmerdam
- * dbfopen now using SAHooks for fileio
- *
- * Revision 1.39 2007/12/04 20:37:56 fwarmerdam
- * preliminary implementation of hooks api for io and errors
- *
- * Revision 1.38 2007/11/21 22:39:56 fwarmerdam
- * close shx file in readonly mode (GDAL #1956)
- *
- * Revision 1.37 2007/10/27 03:31:14 fwarmerdam
- * limit default depth of tree to 12 levels (gdal ticket #1594)
- *
- * Revision 1.36 2007/09/10 23:33:15 fwarmerdam
- * Upstreamed support for visibility flag in SHPAPI_CALL for the needs
- * of GDAL (gdal ticket #1810).
- *
- * Revision 1.35 2007/09/03 19:48:10 fwarmerdam
- * move DBFReadAttribute() static dDoubleField into dbfinfo
- *
- * Revision 1.34 2006/06/17 15:33:32 fwarmerdam
- * added pszWorkField - bug 1202 (rso)
- *
- * Revision 1.33 2006/02/15 01:14:30 fwarmerdam
- * added DBFAddNativeFieldType
- *
- * Revision 1.32 2006/01/26 15:07:32 fwarmerdam
- * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
- *
- * Revision 1.31 2006/01/05 01:27:27 fwarmerdam
- * added dbf deletion mark/fetch
- *
- * Revision 1.30 2005/01/03 22:30:13 fwarmerdam
- * added support for saved quadtrees
- *
- * Revision 1.29 2004/09/26 20:09:35 fwarmerdam
- * avoid rcsid warnings
- *
- * Revision 1.28 2003/12/29 06:02:18 fwarmerdam
- * added cpl_error.h option
- *
- * Revision 1.27 2003/04/21 18:30:37 warmerda
- * added header write/update public methods
- *
- * Revision 1.26 2002/09/29 00:00:08 warmerda
- * added FTLogical and logical attribute read/write calls
- *
- * Revision 1.25 2002/05/07 13:46:30 warmerda
- * added DBFWriteAttributeDirectly().
- *
- * Revision 1.24 2002/04/10 16:59:54 warmerda
- * added SHPRewindObject
- *
- * Revision 1.23 2002/01/15 14:36:07 warmerda
- * updated email address
- *
- * Revision 1.22 2002/01/15 14:32:00 warmerda
- * try to improve SHPAPI_CALL docs
*/
#include <stdio.h>
-#ifdef USE_DBMALLOC
-#include <dbmalloc.h>
-#endif
-
#ifdef USE_CPL
#include "cpl_conv.h"
#endif
#ifdef __cplusplus
-extern "C" {
+extern "C"
+{
#endif
+/************************************************************************/
+/* Version related macros (added in 1.6.0) */
+/************************************************************************/
+
+#define SHAPELIB_VERSION_MAJOR 1
+#define SHAPELIB_VERSION_MINOR 6
+#define SHAPELIB_VERSION_MICRO 0
+
+#define SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro) \
+ ((major) * 10000 + (minor) * 100 + (micro))
+
+#define SHAPELIB_VERSION_NUMBER \
+ SHAPELIB_MAKE_VERSION_NUMBER(SHAPELIB_VERSION_MAJOR, SHAPELIB_VERSION_MINOR, SHAPELIB_VERSION_MICRO)
+
+#define SHAPELIB_AT_LEAST(major, minor, micro) \
+ (SHAPELIB_VERSION_NUMBER >= SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro))
+
/************************************************************************/
/* Configuration options. */
/************************************************************************/
/* -------------------------------------------------------------------- */
#define DISABLE_MULTIPATCH_MEASURE
-/* -------------------------------------------------------------------- */
-/* SHPAPI_CALL */
-/* */
-/* The following two macros are present to allow forcing */
-/* various calling conventions on the Shapelib API. */
-/* */
-/* To force __stdcall conventions (needed to call Shapelib */
-/* from Visual Basic and/or Dephi I believe) the makefile could */
-/* be modified to define: */
-/* */
-/* /DSHPAPI_CALL=__stdcall */
-/* */
-/* If it is desired to force export of the Shapelib API without */
-/* using the shapelib.def file, use the following definition. */
-/* */
-/* /DSHAPELIB_DLLEXPORT */
-/* */
-/* To get both at once it will be necessary to hack this */
-/* include file to define: */
-/* */
-/* #define SHPAPI_CALL __declspec(dllexport) __stdcall */
-/* #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall */
-/* */
-/* The complexity of the situation is partly caused by the */
-/* peculiar requirement of Visual C++ that __stdcall appear */
-/* after any "*"'s in the return value of a function while the */
-/* __declspec(dllexport) must appear before them. */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* SHPAPI_CALL */
+ /* */
+ /* The following two macros are present to allow forcing */
+ /* various calling conventions on the Shapelib API. */
+ /* */
+ /* To force __stdcall conventions (needed to call Shapelib */
+ /* from Visual Basic and/or Delphi I believe) the makefile could */
+ /* be modified to define: */
+ /* */
+ /* /DSHPAPI_CALL=__stdcall */
+ /* */
+ /* If it is desired to force export of the Shapelib API without */
+ /* using the shapelib.def file, use the following definition. */
+ /* */
+ /* /DSHAPELIB_DLLEXPORT */
+ /* */
+ /* To get both at once it will be necessary to hack this */
+ /* include file to define: */
+ /* */
+ /* #define SHPAPI_CALL __declspec(dllexport) __stdcall */
+ /* #define SHPAPI_CALL1 __declspec(dllexport) * __stdcall */
+ /* */
+ /* The complexity of the situation is partly caused by the */
+ /* peculiar requirement of Visual C++ that __stdcall appear */
+ /* after any "*"'s in the return value of a function while the */
+ /* __declspec(dllexport) must appear before them. */
+ /* -------------------------------------------------------------------- */
#ifdef SHAPELIB_DLLEXPORT
-# define SHPAPI_CALL __declspec(dllexport)
-# define SHPAPI_CALL1(x) __declspec(dllexport) x
+#define SHPAPI_CALL __declspec(dllexport)
+#define SHPAPI_CALL1(x) __declspec(dllexport) x
#endif
#ifndef SHPAPI_CALL
-# if defined(USE_GCC_VISIBILITY_FLAG)
-# define SHPAPI_CALL __attribute__ ((visibility("default")))
-# define SHPAPI_CALL1(x) __attribute__ ((visibility("default"))) x
-# else
-# define SHPAPI_CALL
-# endif
+#if defined(USE_GCC_VISIBILITY_FLAG)
+#define SHPAPI_CALL __attribute__((visibility("default")))
+#define SHPAPI_CALL1(x) __attribute__((visibility("default"))) x
+#else
+#define SHPAPI_CALL
#endif
-
-#ifndef SHPAPI_CALL1
-# define SHPAPI_CALL1(x) x SHPAPI_CALL
#endif
-/* -------------------------------------------------------------------- */
-/* Macros for controlling CVSID and ensuring they don't appear */
-/* as unreferenced variables resulting in lots of warnings. */
-/* -------------------------------------------------------------------- */
-#ifndef DISABLE_CVSID
-# if defined(__GNUC__) && __GNUC__ >= 4
-# define SHP_CVSID(string) static const char cpl_cvsid[] __attribute__((used)) = string;
-# else
-# define SHP_CVSID(string) static const char cpl_cvsid[] = string; \
-static const char *cvsid_aw() { return( cvsid_aw() ? NULL : cpl_cvsid ); }
-# endif
-#else
-# define SHP_CVSID(string)
+#ifndef SHPAPI_CALL1
+#define SHPAPI_CALL1(x) x SHPAPI_CALL
#endif
/* -------------------------------------------------------------------- */
/* UTF-8 encoded filenames Unicode filenames */
/* -------------------------------------------------------------------- */
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-# define SHPAPI_WINDOWS
-# define SHPAPI_UTF8_HOOKS
+#define SHPAPI_WINDOWS
+#define SHPAPI_UTF8_HOOKS
#endif
-/* -------------------------------------------------------------------- */
-/* IO/Error hook functions. */
-/* -------------------------------------------------------------------- */
-typedef int *SAFile;
+ /* -------------------------------------------------------------------- */
+ /* IO/Error hook functions. */
+ /* -------------------------------------------------------------------- */
+ typedef int *SAFile;
#ifndef SAOffset
-typedef unsigned long SAOffset;
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ typedef unsigned __int64 SAOffset;
+#else
+ typedef unsigned long SAOffset;
+#endif
#endif
-typedef struct {
- SAFile (*FOpen) ( const char *filename, const char *access);
- SAOffset (*FRead) ( void *p, SAOffset size, SAOffset nmemb, SAFile file);
- SAOffset (*FWrite)( void *p, SAOffset size, SAOffset nmemb, SAFile file);
- SAOffset (*FSeek) ( SAFile file, SAOffset offset, int whence );
- SAOffset (*FTell) ( SAFile file );
- int (*FFlush)( SAFile file );
- int (*FClose)( SAFile file );
- int (*Remove) ( const char *filename );
-
- void (*Error) ( const char *message );
- double (*Atof) ( const char *str );
-} SAHooks;
-
-void SHPAPI_CALL SASetupDefaultHooks( SAHooks *psHooks );
+ typedef struct
+ {
+ SAFile (*FOpen)(const char *filename, const char *access,
+ void *pvUserData);
+ SAOffset (*FRead)(void *p, SAOffset size, SAOffset nmemb, SAFile file);
+ SAOffset (*FWrite)(const void *p, SAOffset size, SAOffset nmemb,
+ SAFile file);
+ SAOffset (*FSeek)(SAFile file, SAOffset offset, int whence);
+ SAOffset (*FTell)(SAFile file);
+ int (*FFlush)(SAFile file);
+ int (*FClose)(SAFile file);
+ int (*Remove)(const char *filename, void *pvUserData);
+
+ void (*Error)(const char *message);
+ double (*Atof)(const char *str);
+ void *pvUserData;
+ } SAHooks;
+
+ void SHPAPI_CALL SASetupDefaultHooks(SAHooks *psHooks);
#ifdef SHPAPI_UTF8_HOOKS
-void SHPAPI_CALL SASetupUtf8Hooks( SAHooks *psHooks );
+ void SHPAPI_CALL SASetupUtf8Hooks(SAHooks *psHooks);
#endif
-/************************************************************************/
-/* SHP Support. */
-/************************************************************************/
-typedef struct tagSHPObject SHPObject;
+ /************************************************************************/
+ /* SHP Support. */
+ /************************************************************************/
+ typedef struct tagSHPObject SHPObject;
-typedef struct
-{
- SAHooks sHooks;
+ typedef struct
+ {
+ SAHooks sHooks;
- SAFile fpSHP;
- SAFile fpSHX;
+ SAFile fpSHP;
+ SAFile fpSHX;
- int nShapeType; /* SHPT_* */
+ int nShapeType; /* SHPT_* */
- unsigned int nFileSize; /* SHP file */
+ unsigned int nFileSize; /* SHP file */
- int nRecords;
- int nMaxRecords;
- unsigned int*panRecOffset;
- unsigned int *panRecSize;
+ int nRecords;
+ int nMaxRecords;
+ unsigned int *panRecOffset;
+ unsigned int *panRecSize;
- double adBoundsMin[4];
- double adBoundsMax[4];
+ double adBoundsMin[4];
+ double adBoundsMax[4];
- int bUpdated;
+ int bUpdated;
- unsigned char *pabyRec;
- int nBufSize;
+ unsigned char *pabyRec;
+ int nBufSize;
- int bFastModeReadObject;
- unsigned char *pabyObjectBuf;
- int nObjectBufSize;
- SHPObject* psCachedObject;
-} SHPInfo;
+ int bFastModeReadObject;
+ unsigned char *pabyObjectBuf;
+ int nObjectBufSize;
+ SHPObject *psCachedObject;
+ } SHPInfo;
-typedef SHPInfo * SHPHandle;
+ typedef SHPInfo *SHPHandle;
/* -------------------------------------------------------------------- */
/* Shape types (nSHPType) */
/* -------------------------------------------------------------------- */
-#define SHPT_NULL 0
-#define SHPT_POINT 1
-#define SHPT_ARC 3
-#define SHPT_POLYGON 5
+#define SHPT_NULL 0
+#define SHPT_POINT 1
+#define SHPT_ARC 3
+#define SHPT_POLYGON 5
#define SHPT_MULTIPOINT 8
-#define SHPT_POINTZ 11
-#define SHPT_ARCZ 13
-#define SHPT_POLYGONZ 15
+#define SHPT_POINTZ 11
+#define SHPT_ARCZ 13
+#define SHPT_POLYGONZ 15
#define SHPT_MULTIPOINTZ 18
-#define SHPT_POINTM 21
-#define SHPT_ARCM 23
-#define SHPT_POLYGONM 25
+#define SHPT_POINTM 21
+#define SHPT_ARCM 23
+#define SHPT_POLYGONM 25
#define SHPT_MULTIPOINTM 28
#define SHPT_MULTIPATCH 31
-/* -------------------------------------------------------------------- */
-/* Part types - everything but SHPT_MULTIPATCH just uses */
-/* SHPP_RING. */
-/* -------------------------------------------------------------------- */
-
-#define SHPP_TRISTRIP 0
-#define SHPP_TRIFAN 1
-#define SHPP_OUTERRING 2
-#define SHPP_INNERRING 3
-#define SHPP_FIRSTRING 4
-#define SHPP_RING 5
-
-/* -------------------------------------------------------------------- */
-/* SHPObject - represents on shape (without attributes) read */
-/* from the .shp file. */
-/* -------------------------------------------------------------------- */
-struct tagSHPObject
-{
- int nSHPType;
-
- int nShapeId; /* -1 is unknown/unassigned */
-
- int nParts;
- int *panPartStart;
- int *panPartType;
-
- int nVertices;
- double *padfX;
- double *padfY;
- double *padfZ;
- double *padfM;
-
- double dfXMin;
- double dfYMin;
- double dfZMin;
- double dfMMin;
-
- double dfXMax;
- double dfYMax;
- double dfZMax;
- double dfMMax;
-
- int bMeasureIsUsed;
- int bFastModeReadObject;
-};
-
-/* -------------------------------------------------------------------- */
-/* SHP API Prototypes */
-/* -------------------------------------------------------------------- */
-
-/* If pszAccess is read-only, the fpSHX field of the returned structure */
-/* will be NULL as it is not necessary to keep the SHX file open */
-SHPHandle SHPAPI_CALL
- SHPOpen( const char * pszShapeFile, const char * pszAccess );
-SHPHandle SHPAPI_CALL
- SHPOpenLL( const char *pszShapeFile, const char *pszAccess,
- SAHooks *psHooks );
-SHPHandle SHPAPI_CALL
- SHPOpenLLEx( const char *pszShapeFile, const char *pszAccess,
- SAHooks *psHooks, int bRestoreSHX );
-
-int SHPAPI_CALL
- SHPRestoreSHX( const char *pszShapeFile, const char *pszAccess,
- SAHooks *psHooks );
-
-/* If setting bFastMode = TRUE, the content of SHPReadObject() is owned by the SHPHandle. */
-/* So you cannot have 2 valid instances of SHPReadObject() simultaneously. */
-/* The SHPObject padfZ and padfM members may be NULL depending on the geometry */
-/* type. It is illegal to free at hand any of the pointer members of the SHPObject structure */
-void SHPAPI_CALL SHPSetFastModeReadObject( SHPHandle hSHP, int bFastMode );
-
-SHPHandle SHPAPI_CALL
- SHPCreate( const char * pszShapeFile, int nShapeType );
-SHPHandle SHPAPI_CALL
- SHPCreateLL( const char * pszShapeFile, int nShapeType,
- SAHooks *psHooks );
-void SHPAPI_CALL
- SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
- double * padfMinBound, double * padfMaxBound );
-
-SHPObject SHPAPI_CALL1(*)
- SHPReadObject( SHPHandle hSHP, int iShape );
-int SHPAPI_CALL
- SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject * psObject );
-
-void SHPAPI_CALL
- SHPDestroyObject( SHPObject * psObject );
-void SHPAPI_CALL
- SHPComputeExtents( SHPObject * psObject );
-SHPObject SHPAPI_CALL1(*)
- SHPCreateObject( int nSHPType, int nShapeId, int nParts,
- const int * panPartStart, const int * panPartType,
- int nVertices,
- const double * padfX, const double * padfY,
- const double * padfZ, const double * padfM );
-SHPObject SHPAPI_CALL1(*)
- SHPCreateSimpleObject( int nSHPType, int nVertices,
- const double * padfX,
- const double * padfY,
- const double * padfZ );
-
-int SHPAPI_CALL
- SHPRewindObject( SHPHandle hSHP, SHPObject * psObject );
-
-void SHPAPI_CALL SHPClose( SHPHandle hSHP );
-void SHPAPI_CALL SHPWriteHeader( SHPHandle hSHP );
-
-const char SHPAPI_CALL1(*)
- SHPTypeName( int nSHPType );
-const char SHPAPI_CALL1(*)
- SHPPartTypeName( int nPartType );
+ /* -------------------------------------------------------------------- */
+ /* Part types - everything but SHPT_MULTIPATCH just uses */
+ /* SHPP_RING. */
+ /* -------------------------------------------------------------------- */
+
+#define SHPP_TRISTRIP 0
+#define SHPP_TRIFAN 1
+#define SHPP_OUTERRING 2
+#define SHPP_INNERRING 3
+#define SHPP_FIRSTRING 4
+#define SHPP_RING 5
+
+ /* -------------------------------------------------------------------- */
+ /* SHPObject - represents on shape (without attributes) read */
+ /* from the .shp file. */
+ /* -------------------------------------------------------------------- */
+ struct tagSHPObject
+ {
+ int nSHPType;
+
+ int nShapeId; /* -1 is unknown/unassigned */
+
+ int nParts;
+ int *panPartStart;
+ int *panPartType;
+
+ int nVertices;
+ double *padfX;
+ double *padfY;
+ double *padfZ;
+ double *padfM;
+
+ double dfXMin;
+ double dfYMin;
+ double dfZMin;
+ double dfMMin;
+
+ double dfXMax;
+ double dfYMax;
+ double dfZMax;
+ double dfMMax;
+
+ int bMeasureIsUsed;
+ int bFastModeReadObject;
+ };
+
+ /* -------------------------------------------------------------------- */
+ /* SHP API Prototypes */
+ /* -------------------------------------------------------------------- */
+
+ /* If pszAccess is read-only, the fpSHX field of the returned structure */
+ /* will be NULL as it is not necessary to keep the SHX file open */
+ SHPHandle SHPAPI_CALL SHPOpen(const char *pszShapeFile,
+ const char *pszAccess);
+ SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszShapeFile,
+ const char *pszAccess,
+ const SAHooks *psHooks);
+ SHPHandle SHPAPI_CALL SHPOpenLLEx(const char *pszShapeFile,
+ const char *pszAccess,
+ const SAHooks *psHooks, int bRestoreSHX);
+
+ int SHPAPI_CALL SHPRestoreSHX(const char *pszShapeFile,
+ const char *pszAccess,
+ const SAHooks *psHooks);
+
+ /* If setting bFastMode = TRUE, the content of SHPReadObject() is owned by the SHPHandle. */
+ /* So you cannot have 2 valid instances of SHPReadObject() simultaneously. */
+ /* The SHPObject padfZ and padfM members may be NULL depending on the geometry */
+ /* type. It is illegal to free at hand any of the pointer members of the SHPObject structure */
+ void SHPAPI_CALL SHPSetFastModeReadObject(SHPHandle hSHP, int bFastMode);
+
+ SHPHandle SHPAPI_CALL SHPCreate(const char *pszShapeFile, int nShapeType);
+ SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszShapeFile, int nShapeType,
+ const SAHooks *psHooks);
+ void SHPAPI_CALL SHPGetInfo(SHPHandle hSHP, int *pnEntities,
+ int *pnShapeType, double *padfMinBound,
+ double *padfMaxBound);
+
+ SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle hSHP, int iShape);
+ int SHPAPI_CALL SHPWriteObject(SHPHandle hSHP, int iShape,
+ SHPObject *psObject);
+
+ void SHPAPI_CALL SHPDestroyObject(SHPObject *psObject);
+ void SHPAPI_CALL SHPComputeExtents(SHPObject *psObject);
+ SHPObject SHPAPI_CALL1(*)
+ SHPCreateObject(int nSHPType, int nShapeId, int nParts,
+ const int *panPartStart, const int *panPartType,
+ int nVertices, const double *padfX, const double *padfY,
+ const double *padfZ, const double *padfM);
+ SHPObject SHPAPI_CALL1(*)
+ SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX,
+ const double *padfY, const double *padfZ);
+
+ int SHPAPI_CALL SHPRewindObject(SHPHandle hSHP, SHPObject *psObject);
+
+ void SHPAPI_CALL SHPClose(SHPHandle hSHP);
+ void SHPAPI_CALL SHPWriteHeader(SHPHandle hSHP);
+
+ const char SHPAPI_CALL1(*) SHPTypeName(int nSHPType);
+ const char SHPAPI_CALL1(*) SHPPartTypeName(int nPartType);
/* -------------------------------------------------------------------- */
/* Shape quadtree indexing API. */
/* upper limit of tree levels for automatic estimation */
#define MAX_DEFAULT_TREE_DEPTH 12
-typedef struct shape_tree_node
-{
- /* region covered by this node */
- double adfBoundsMin[4];
- double adfBoundsMax[4];
+ typedef struct shape_tree_node
+ {
+ /* region covered by this node */
+ double adfBoundsMin[4];
+ double adfBoundsMax[4];
- /* list of shapes stored at this node. The papsShapeObj pointers
- or the whole list can be NULL */
- int nShapeCount;
- int *panShapeIds;
- SHPObject **papsShapeObj;
+ /* list of shapes stored at this node. The papsShapeObj pointers
+ or the whole list can be NULL */
+ int nShapeCount;
+ int *panShapeIds;
+ SHPObject **papsShapeObj;
- int nSubNodes;
- struct shape_tree_node *apsSubNode[MAX_SUBNODE];
+ int nSubNodes;
+ struct shape_tree_node *apsSubNode[MAX_SUBNODE];
-} SHPTreeNode;
+ } SHPTreeNode;
-typedef struct
-{
- SHPHandle hSHP;
+ typedef struct
+ {
+ SHPHandle hSHP;
- int nMaxDepth;
- int nDimension;
- int nTotalCount;
+ int nMaxDepth;
+ int nDimension;
+ int nTotalCount;
- SHPTreeNode *psRoot;
-} SHPTree;
+ SHPTreeNode *psRoot;
+ } SHPTree;
-SHPTree SHPAPI_CALL1(*)
- SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
- double *padfBoundsMin, double *padfBoundsMax );
-void SHPAPI_CALL
- SHPDestroyTree( SHPTree * hTree );
+ SHPTree SHPAPI_CALL1(*)
+ SHPCreateTree(SHPHandle hSHP, int nDimension, int nMaxDepth,
+ const double *padfBoundsMin, const double *padfBoundsMax);
+ void SHPAPI_CALL SHPDestroyTree(SHPTree *hTree);
-int SHPAPI_CALL
- SHPWriteTree( SHPTree *hTree, const char * pszFilename );
+ int SHPAPI_CALL SHPWriteTree(SHPTree *hTree, const char *pszFilename);
-int SHPAPI_CALL
- SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
-int SHPAPI_CALL
- SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
+ int SHPAPI_CALL SHPTreeAddShapeId(SHPTree *hTree, SHPObject *psObject);
+ int SHPAPI_CALL SHPTreeRemoveShapeId(SHPTree *hTree, int nShapeId);
-void SHPAPI_CALL
- SHPTreeTrimExtraNodes( SHPTree * hTree );
+ void SHPAPI_CALL SHPTreeTrimExtraNodes(SHPTree *hTree);
-int SHPAPI_CALL1(*)
- SHPTreeFindLikelyShapes( SHPTree * hTree,
- double * padfBoundsMin,
- double * padfBoundsMax,
- int * );
-int SHPAPI_CALL
- SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
+ int SHPAPI_CALL1(*)
+ SHPTreeFindLikelyShapes(SHPTree *hTree, double *padfBoundsMin,
+ double *padfBoundsMax, int *);
+ int SHPAPI_CALL SHPCheckBoundsOverlap(const double *, const double *,
+ const double *, const double *, int);
-int SHPAPI_CALL1(*)
-SHPSearchDiskTree( FILE *fp,
- double *padfBoundsMin, double *padfBoundsMax,
- int *pnShapeCount );
+ int SHPAPI_CALL1(*)
+ SHPSearchDiskTree(FILE *fp, double *padfBoundsMin,
+ double *padfBoundsMax, int *pnShapeCount);
-typedef struct SHPDiskTreeInfo* SHPTreeDiskHandle;
+ typedef struct SHPDiskTreeInfo *SHPTreeDiskHandle;
-SHPTreeDiskHandle SHPAPI_CALL
- SHPOpenDiskTree( const char* pszQIXFilename,
- SAHooks *psHooks );
+ SHPTreeDiskHandle SHPAPI_CALL SHPOpenDiskTree(const char *pszQIXFilename,
+ const SAHooks *psHooks);
-void SHPAPI_CALL
- SHPCloseDiskTree( SHPTreeDiskHandle hDiskTree );
+ void SHPAPI_CALL SHPCloseDiskTree(SHPTreeDiskHandle hDiskTree);
-int SHPAPI_CALL1(*)
-SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree,
- double *padfBoundsMin, double *padfBoundsMax,
- int *pnShapeCount );
+ int SHPAPI_CALL1(*)
+ SHPSearchDiskTreeEx(SHPTreeDiskHandle hDiskTree, double *padfBoundsMin,
+ double *padfBoundsMax, int *pnShapeCount);
-int SHPAPI_CALL
- SHPWriteTreeLL(SHPTree *hTree, const char *pszFilename, SAHooks *psHooks );
+ int SHPAPI_CALL SHPWriteTreeLL(SHPTree *hTree, const char *pszFilename,
+ const SAHooks *psHooks);
-/* -------------------------------------------------------------------- */
-/* SBN Search API */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* SBN Search API */
+ /* -------------------------------------------------------------------- */
-typedef struct SBNSearchInfo* SBNSearchHandle;
+ typedef struct SBNSearchInfo *SBNSearchHandle;
-SBNSearchHandle SHPAPI_CALL
- SBNOpenDiskTree( const char* pszSBNFilename,
- SAHooks *psHooks );
+ SBNSearchHandle SHPAPI_CALL SBNOpenDiskTree(const char *pszSBNFilename,
+ const SAHooks *psHooks);
-void SHPAPI_CALL
- SBNCloseDiskTree( SBNSearchHandle hSBN );
+ void SHPAPI_CALL SBNCloseDiskTree(SBNSearchHandle hSBN);
-int SHPAPI_CALL1(*)
-SBNSearchDiskTree( SBNSearchHandle hSBN,
- double *padfBoundsMin, double *padfBoundsMax,
- int *pnShapeCount );
+ int SHPAPI_CALL1(*)
+ SBNSearchDiskTree(SBNSearchHandle hSBN, const double *padfBoundsMin,
+ const double *padfBoundsMax, int *pnShapeCount);
-int SHPAPI_CALL1(*)
-SBNSearchDiskTreeInteger( SBNSearchHandle hSBN,
- int bMinX, int bMinY, int bMaxX, int bMaxY,
- int *pnShapeCount );
+ int SHPAPI_CALL1(*)
+ SBNSearchDiskTreeInteger(SBNSearchHandle hSBN, int bMinX, int bMinY,
+ int bMaxX, int bMaxY, int *pnShapeCount);
-void SHPAPI_CALL SBNSearchFreeIds( int* panShapeId );
+ void SHPAPI_CALL SBNSearchFreeIds(int *panShapeId);
-/************************************************************************/
-/* DBF Support. */
-/************************************************************************/
-typedef struct
-{
- SAHooks sHooks;
+ /************************************************************************/
+ /* DBF Support. */
+ /************************************************************************/
+ typedef struct
+ {
+ SAHooks sHooks;
- SAFile fp;
+ SAFile fp;
- int nRecords;
+ int nRecords;
- int nRecordLength; /* Must fit on uint16 */
- int nHeaderLength; /* File header length (32) + field
- descriptor length + spare space.
- Must fit on uint16 */
- int nFields;
- int *panFieldOffset;
- int *panFieldSize;
- int *panFieldDecimals;
- char *pachFieldType;
+ int nRecordLength; /* Must fit on uint16 */
+ int nHeaderLength; /* File header length (32) + field
+ descriptor length + spare space.
+ Must fit on uint16 */
+ int nFields;
+ int *panFieldOffset;
+ int *panFieldSize;
+ int *panFieldDecimals;
+ char *pachFieldType;
- char *pszHeader; /* Field descriptors */
+ char *pszHeader; /* Field descriptors */
- int nCurrentRecord;
- int bCurrentRecordModified;
- char *pszCurrentRecord;
+ int nCurrentRecord;
+ int bCurrentRecordModified;
+ char *pszCurrentRecord;
- int nWorkFieldLength;
- char *pszWorkField;
+ int nWorkFieldLength;
+ char *pszWorkField;
- int bNoHeader;
- int bUpdated;
+ int bNoHeader;
+ int bUpdated;
- union
- {
- double dfDoubleField;
- int nIntField;
- } fieldValue;
+ union
+ {
+ double dfDoubleField;
+ int nIntField;
+ } fieldValue;
+
+ int iLanguageDriver;
+ char *pszCodePage;
- int iLanguageDriver;
- char *pszCodePage;
+ int nUpdateYearSince1900; /* 0-255 */
+ int nUpdateMonth; /* 1-12 */
+ int nUpdateDay; /* 1-31 */
- int nUpdateYearSince1900; /* 0-255 */
- int nUpdateMonth; /* 1-12 */
- int nUpdateDay; /* 1-31 */
+ int bWriteEndOfFileChar; /* defaults to TRUE */
- int bWriteEndOfFileChar; /* defaults to TRUE */
-} DBFInfo;
+ int bRequireNextWriteSeek;
+ } DBFInfo;
-typedef DBFInfo * DBFHandle;
+ typedef DBFInfo *DBFHandle;
-typedef enum {
- FTString,
- FTInteger,
- FTDouble,
- FTLogical,
- FTDate,
- FTInvalid
-} DBFFieldType;
+ typedef enum
+ {
+ FTString,
+ FTInteger,
+ FTDouble,
+ FTLogical,
+ FTDate,
+ FTInvalid
+ } DBFFieldType;
/* Field descriptor/header size */
-#define XBASE_FLDHDR_SZ 32
+#define XBASE_FLDHDR_SZ 32
/* Shapelib read up to 11 characters, even if only 10 should normally be used */
-#define XBASE_FLDNAME_LEN_READ 11
+#define XBASE_FLDNAME_LEN_READ 11
/* On writing, we limit to 10 characters */
#define XBASE_FLDNAME_LEN_WRITE 10
/* Normally only 254 characters should be used. We tolerate 255 historically */
-#define XBASE_FLD_MAX_WIDTH 255
-
-DBFHandle SHPAPI_CALL
- DBFOpen( const char * pszDBFFile, const char * pszAccess );
-DBFHandle SHPAPI_CALL
- DBFOpenLL( const char * pszDBFFile, const char * pszAccess,
- SAHooks *psHooks );
-DBFHandle SHPAPI_CALL
- DBFCreate( const char * pszDBFFile );
-DBFHandle SHPAPI_CALL
- DBFCreateEx( const char * pszDBFFile, const char * pszCodePage );
-DBFHandle SHPAPI_CALL
- DBFCreateLL( const char * pszDBFFile, const char * pszCodePage, SAHooks *psHooks );
-
-int SHPAPI_CALL
- DBFGetFieldCount( DBFHandle psDBF );
-int SHPAPI_CALL
- DBFGetRecordCount( DBFHandle psDBF );
-int SHPAPI_CALL
- DBFAddField( DBFHandle hDBF, const char * pszFieldName,
- DBFFieldType eType, int nWidth, int nDecimals );
-
-int SHPAPI_CALL
- DBFAddNativeFieldType( DBFHandle hDBF, const char * pszFieldName,
- char chType, int nWidth, int nDecimals );
-
-int SHPAPI_CALL
- DBFDeleteField( DBFHandle hDBF, int iField );
-
-int SHPAPI_CALL
- DBFReorderFields( DBFHandle psDBF, int* panMap );
-
-int SHPAPI_CALL
- DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
- char chType, int nWidth, int nDecimals );
-
-DBFFieldType SHPAPI_CALL
- DBFGetFieldInfo( DBFHandle psDBF, int iField,
- char * pszFieldName, int * pnWidth, int * pnDecimals );
-
-int SHPAPI_CALL
- DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
-
-int SHPAPI_CALL
- DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
-double SHPAPI_CALL
- DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
-const char SHPAPI_CALL1(*)
- DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
-const char SHPAPI_CALL1(*)
- DBFReadLogicalAttribute( DBFHandle hDBF, int iShape, int iField );
-int SHPAPI_CALL
- DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
-
-int SHPAPI_CALL
- DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField,
- int nFieldValue );
-int SHPAPI_CALL
- DBFWriteDoubleAttribute( DBFHandle hDBF, int iShape, int iField,
- double dFieldValue );
-int SHPAPI_CALL
- DBFWriteStringAttribute( DBFHandle hDBF, int iShape, int iField,
- const char * pszFieldValue );
-int SHPAPI_CALL
- DBFWriteNULLAttribute( DBFHandle hDBF, int iShape, int iField );
-
-int SHPAPI_CALL
- DBFWriteLogicalAttribute( DBFHandle hDBF, int iShape, int iField,
- const char lFieldValue);
-int SHPAPI_CALL
- DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
- void * pValue );
-const char SHPAPI_CALL1(*)
- DBFReadTuple(DBFHandle psDBF, int hEntity );
-int SHPAPI_CALL
- DBFWriteTuple(DBFHandle psDBF, int hEntity, void * pRawTuple );
-
-int SHPAPI_CALL DBFIsRecordDeleted( DBFHandle psDBF, int iShape );
-int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
- int bIsDeleted );
-
-DBFHandle SHPAPI_CALL
- DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
-
-void SHPAPI_CALL
- DBFClose( DBFHandle hDBF );
-void SHPAPI_CALL
- DBFUpdateHeader( DBFHandle hDBF );
-char SHPAPI_CALL
- DBFGetNativeFieldType( DBFHandle hDBF, int iField );
-
-const char SHPAPI_CALL1(*)
- DBFGetCodePage(DBFHandle psDBF );
-
-void SHPAPI_CALL
- DBFSetLastModifiedDate( DBFHandle psDBF, int nYYSince1900, int nMM, int nDD );
-
-void SHPAPI_CALL DBFSetWriteEndOfFileChar( DBFHandle psDBF, int bWriteFlag );
+#define XBASE_FLD_MAX_WIDTH 255
+
+ DBFHandle SHPAPI_CALL DBFOpen(const char *pszDBFFile,
+ const char *pszAccess);
+ DBFHandle SHPAPI_CALL DBFOpenLL(const char *pszDBFFile,
+ const char *pszAccess,
+ const SAHooks *psHooks);
+ DBFHandle SHPAPI_CALL DBFCreate(const char *pszDBFFile);
+ DBFHandle SHPAPI_CALL DBFCreateEx(const char *pszDBFFile,
+ const char *pszCodePage);
+ DBFHandle SHPAPI_CALL DBFCreateLL(const char *pszDBFFile,
+ const char *pszCodePage,
+ const SAHooks *psHooks);
+
+ int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF);
+ int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF);
+ int SHPAPI_CALL DBFAddField(DBFHandle hDBF, const char *pszFieldName,
+ DBFFieldType eType, int nWidth, int nDecimals);
+
+ int SHPAPI_CALL DBFAddNativeFieldType(DBFHandle hDBF,
+ const char *pszFieldName, char chType,
+ int nWidth, int nDecimals);
+
+ int SHPAPI_CALL DBFDeleteField(DBFHandle hDBF, int iField);
+
+ int SHPAPI_CALL DBFReorderFields(DBFHandle psDBF, const int *panMap);
+
+ int SHPAPI_CALL DBFAlterFieldDefn(DBFHandle psDBF, int iField,
+ const char *pszFieldName, char chType,
+ int nWidth, int nDecimals);
+
+ DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField,
+ char *pszFieldName, int *pnWidth,
+ int *pnDecimals);
+
+ int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
+
+ int SHPAPI_CALL DBFReadIntegerAttribute(DBFHandle hDBF, int iShape,
+ int iField);
+ double SHPAPI_CALL DBFReadDoubleAttribute(DBFHandle hDBF, int iShape,
+ int iField);
+ const char SHPAPI_CALL1(*)
+ DBFReadStringAttribute(DBFHandle hDBF, int iShape, int iField);
+ const char SHPAPI_CALL1(*)
+ DBFReadLogicalAttribute(DBFHandle hDBF, int iShape, int iField);
+ int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle hDBF, int iShape, int iField);
+
+ int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle hDBF, int iShape,
+ int iField, int nFieldValue);
+ int SHPAPI_CALL DBFWriteDoubleAttribute(DBFHandle hDBF, int iShape,
+ int iField, double dFieldValue);
+ int SHPAPI_CALL DBFWriteStringAttribute(DBFHandle hDBF, int iShape,
+ int iField,
+ const char *pszFieldValue);
+ int SHPAPI_CALL DBFWriteNULLAttribute(DBFHandle hDBF, int iShape,
+ int iField);
+
+ int SHPAPI_CALL DBFWriteLogicalAttribute(DBFHandle hDBF, int iShape,
+ int iField,
+ const char lFieldValue);
+ int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity,
+ int iField, const void *pValue);
+ const char SHPAPI_CALL1(*) DBFReadTuple(DBFHandle psDBF, int hEntity);
+ int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity,
+ const void *pRawTuple);
+
+ int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape);
+ int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape,
+ int bIsDeleted);
+
+ DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF,
+ const char *pszFilename);
+
+ void SHPAPI_CALL DBFClose(DBFHandle hDBF);
+ void SHPAPI_CALL DBFUpdateHeader(DBFHandle hDBF);
+ char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle hDBF, int iField);
+
+ const char SHPAPI_CALL1(*) DBFGetCodePage(DBFHandle psDBF);
+
+ void SHPAPI_CALL DBFSetLastModifiedDate(DBFHandle psDBF, int nYYSince1900,
+ int nMM, int nDD);
+
+ void SHPAPI_CALL DBFSetWriteEndOfFileChar(DBFHandle psDBF, int bWriteFlag);
#ifdef __cplusplus
}
<h2>What is a Shapefile?</h2>
If you don't know, you probably don't need this library. The Shapefile
-format is a working and interchange format promulagated by
+format is a working and interchange format promulgated by
<a href="http://www.esri.com/">ESRI</a> for simple vector data with attributes.
<p>
-An excellent <a href="dl/shapefile.pdf">white paper</a> on the shapefile format
-is available from ESRI,
-but it is .pdf format, so you will need Adobe Acrobat to browse it.<p>
+An excellent <a href="https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf">white paper</a>
+on the shapefile format is available from ESRI.<p>
The file format actually consists of three files.<p>
<pre>
XXX.shp - holds the actual vertices.
XXX.shx - hold index data pointing to the structures in the .shp file.
-XXX.dbf - holds the attributes in xBase (dBase) format.
+XXX.dbf - holds the attributes in xBase (dBase) format.
</pre>
<h2>Download</h2>
Source code, and some other odds and ends can be downloaded from
<a href="http://download.osgeo.org/shapelib">http://download.osgeo.org/shapelib</a>.<p>
-Shapelib is available for anonymous CVS access:
-
-<pre>
- cvs -d :pserver:cvsanon@cvs.maptools.org:/cvs/maptools/cvsroot login
- Password: (hit enter)
- cvs -d :pserver:cvsanon@cvs.maptools.org:/cvs/maptools/cvsroot co shapelib
-</pre>
+Shapelib repository is at
+<a href="https://github.com/OSGeo/shapelib">https://github.com/OSGeo/shapelib</a><p>
<h2>Bugs, Maintainance and Support</h2>
-This library is maintained by <a href="http://pobox.com/~warmerdam">Frank
-Warmerdam</a>. Please send me bug reports, patches and suggestions for the
+This library is maintained by <a href="http://pobox.com/~warmerdam">Frank
+Warmerdam</a>. Please send me bug reports, patches and suggestions for the
library via the <a href="http://bugzilla.maptools.org/enter_bug.cgi?product=Shapelib">maptools.org Bugzilla</a>. Shapelib bugs can also be
<a href="http://bugzilla.maptools.org/query.cgi?product=Shapelib">queried</a>.
<p>
-Shapelib is hosted at
+Shapelib is hosted at
<a href="http://shapelib.maptools.org">shapelib.maptools.org</a>. A mailing
-list for discussion of how to use shapelib, and announcing new releases
-<a href="http://lists.maptools.org/mailman/listinfo/shapelib/">is
-available</a>. To get notification of new releases of Shapelib <i>subscribe</i> to
+list for discussion of how to use shapelib, and announcing new releases
+<a href="http://lists.maptools.org/mailman/listinfo/shapelib/">is
+available</a>. To get notification of new releases of Shapelib <i>subscribe</i> to
the project mailing list at https://lists.osgeo.org/pipermail/shapelib/.<p>
<h2>Credits</h2>
<ul>
<li> Bill Miller (NY-DOT) for shputils.c
-<li> Carl Anderson for the contents of the contrib directory, and
+<li> Carl Anderson for the contents of the contrib directory, and
the "tuple" additions to dbfopen.c.
<li> Andrea Giacomelli for patches for dbfopen.c.
<li> Doug Matthews for portability improvements.
<h2>In Memorium</h2>
I would like to dedicate Shapelib to the memory of Sol Katz. While I never
-met him in person, his generous contributions to the GIS community took
+met him in person, his generous contributions to the GIS community took
many forms, including free distribution of a variety of GIS translators
-with source. The fact that he used this Shapelib in some of his utilities,
-and thanked me was a great encouragement to me. I hope I can do his memory
+with source. The fact that he used this Shapelib in some of his utilities,
+and thanked me was a great encouragement to me. I hope I can do his memory
honour by trying to contribute in a similar fashion.<p>
<h2>Portability</h2>
The shputils.c module is contributed, and may not take the same approach
to portability as the rest of the package.<p>
-On Linux, and most unix systems it should be possible to build and
+On Linux, and most unix systems it should be possible to build and
install shapefile support as a shared library using the "lib" and "lib_install"
targets of the Makefile. Note that this Makefile doesn't use autoconf
mechanisms and will generally require some hand tailoring for your environment.
<ul>
-<li> You can't modify the vertices of existing structures (though you
- can update the attributes of existing structures, and create new
+<li> You can't modify the vertices of existing structures (though you
+ can update the attributes of existing structures, and create new
structures).<p>
-<li> Not written in such a way as to be particularly fast. This is
+<li> Not written in such a way as to be particularly fast. This is
particularly true of the 1.2 API. For applications more concerned with
speed it may be worth using the V1.1 API.<p>
<li> <a href="codepage.html">Language ID / Code Page mappings</a><p>
-<li> Shapelib is used within the multiformat
-<a href="http://ogr.maptools.org/">OGR</a> library. If you are looking for a
+<li> Shapelib is used within the multiformat
+<a href="http://ogr.maptools.org/">OGR</a> library. If you are looking for a
high level C++ library with support for many geospatial vector formats you
might want to check it out.<p>
-<li> Ari Jolma has produced an initial <b>perl</b> binding on top of shapelib,
-which can be found at CPAN as Geo::ShapeFile under the
+<li> Ari Jolma has produced an initial <b>perl</b> binding on top of shapelib,
+which can be found at CPAN as Geo::ShapeFile under the
<a href="http://www.cpan.org/modules/by-module/Geo/">Geo</a> module.
<p>
-<li> Bernhard Herzog has produced <b>python</b> bindings for Shapelib with
-SWIG, available at <a href="http://ftp.intevation.de/users/bh/pyshapelib/">http://ftp.intevation.de/users/bh/pyshapelib</a>. A new version not using swig is
+<li> Bernhard Herzog has produced <b>python</b> bindings for Shapelib with
+SWIG, available at <a href="http://ftp.intevation.de/users/bh/pyshapelib/">http://ftp.intevation.de/users/bh/pyshapelib</a>. A new version not using swig is
available as <a href="http://wald.intevation.org/plugins/scmsvn/viewcvs.php/trunk/thuban/libraries/pyshapelib/?root=thuban">part of Thuban</a>.<p>
<li> <a href="http://www.triplexware.huckfinn.de/shpapi.html">Delphi</a>
bindings for Shapelib courtesy of Alexander Weidauer.<p>
-<li> Miguel Filgueiras has implemented
+<li> Miguel Filgueiras has implemented
<a href="http://www.ncc.up.pt/gpsmanshp/">Tcl</a> bindings for Shapelib
as part of <a href="http://www.ncc.up.pt/gpsman/">GPSMan</a>.<p>
<li> David Gancarz has implemented a Microsoft
<a href="dl/contrib/DotNetArchive.zip">.NET wrapper</a> for
-Shapelib. An example of using shapelib with VB6 is also icluded in the .NET wrapper project file.<p>
+Shapelib. An example of using shapelib with VB6 is also included in the .NET wrapper project file.<p>
-<li> Andrey Hristov (php at hristov dot com) has developed a PHP extension
+<li> Andrey Hristov (php at hristov dot com) has developed a PHP extension
based on Shapelib. It can be found in CVS at http://cvs.php.net/pecl/shp.<p>
<li> Toyoda Eizi has developed Ruby bindings found at
<li> Tom Russo has implemented a shpcs2cs program, which reprojects shapefiles
using arguments similar to the PROJ.4 cs2cs program including datum conversion.
-Use as an alternate to the contrib/shpproj which doesn't do datums. It is
+Use as an alternate to the contrib/shpproj which doesn't do datums. It is
available at the bottom of Tom's <a href="http://www.swcp.com/~russo/shape_web/">Xastir Shapefile Resources</a> page. <p>
-<li>
-Andrew Williamson's
+<li>
+Andrew Williamson's
<a href="http://www.geocities.com/SiliconValley/Haven/2295/useful.html">Useful
Scripts and Stuff</a> page for ArcView, which includes ShapeChecker.<p>
<li> The <a href="http://arcscripts.esri.com/details.asp?dbid=11810">ShapeFile Read/Write OCX</a> is another option for Visual Basic programmers.<p>
-<li> <a href="http://www.casa.ucl.ac.uk/sanjay/software_isovistanalyst.htm">Isovist Analyst</a> is a sort-of-free isovist generating extension for
+<li> <a href="http://www.casa.ucl.ac.uk/sanjay/software_isovistanalyst.htm">Isovist Analyst</a> is a sort-of-free isovist generating extension for
ArcView using shapelib.<p>
-<li> <a href="http://www.obviously.com/gis/shpdiff/">shpdiff</a> utility
+<li> <a href="http://www.obviously.com/gis/shpdiff/">shpdiff</a> utility
by Bryce Nesbitt.<p>
-<li> <a href="http://www.aequometer.de/">Aequometer</a>: a program for
+<li> <a href="http://www.aequometer.de/">Aequometer</a>: a program for
MS Excel to calculate the area of polygons and export as shapefiles.<p>
</ul>
3D Shape Types (may include "measure" values for vertices):
- #define SHPT_POINTZ 11
+ #define SHPT_POINTZ 11
#define SHPT_ARCZ 13
#define SHPT_POLYGONZ 15
#define SHPT_MULTIPOINTZ 18
int nParts; # of Parts (0 implies single part with no info)
int *panPartStart; Start Vertex of part
int *panPartType; Part Type (SHPP_RING if not SHPT_MULTIPATCH)
-
- int nVertices; Vertex list
- double *padfX;
+
+ int nVertices; Vertex list
+ double *padfX;
double *padfY;
double *padfZ; (all zero if not provided)
double *padfM; (all zero if not provided)
just be the path plus the basename of the pair.
pszAccess: The fopen() style access string. At this time only
- "rb" (read-only binary) and "rb+" (read/write binary)
+ "rb" (read-only binary) and "rb+" (read/write binary)
should be used.
</pre>
The SHPOpen() function should be used to establish access to the two files
- for accessing vertices (.shp and .shx). Note that both files have to
+ for accessing vertices (.shp and .shx). Note that both files have to
be in the indicated directory, and must have the expected extensions in
- lower case. The returned SHPHandle is passed to other access functions,
- and SHPClose() should be invoked to recover resources, and flush changes
+ lower case. The returned SHPHandle is passed to other access functions,
+ and SHPClose() should be invoked to recover resources, and flush changes
to disk when complete.<p>
<!-------------------------------------------------------------------------->
void SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
double * padfMinBound, double * padfMaxBound );
- hSHP: The handle previously returned by SHPOpen()
+ hSHP: The handle previously returned by SHPOpen()
or SHPCreate().
pnEntities: A pointer to an integer into which the number of
pnShapetype: A pointer to an integer into which the shapetype
of this file should be placed. Shapefiles may contain
- either SHPT_POINT, SHPT_ARC, SHPT_POLYGON or
+ either SHPT_POINT, SHPT_ARC, SHPT_POLYGON or
SHPT_MULTIPOINT entities. This may be NULL.
padfMinBound: The X, Y, Z and M minimum values will be placed into
this four entry array. This may be NULL.
-
+
padfMaxBound: The X, Y, Z and M maximum values will be placed into
this four entry array. This may be NULL.
</pre>
The SHPGetInfo() function retrieves various information about shapefile
- as a whole. The bounds are read from the file header, and may be
+ as a whole. The bounds are read from the file header, and may be
inaccurate if the file was improperly generated. <p>
-
+
<!-------------------------------------------------------------------------->
<h2>SHPReadObject()</h2>
<pre>
SHPObject *SHPReadObject( SHPHandle hSHP, int iShape );
- hSHP: The handle previously returned by SHPOpen()
+ hSHP: The handle previously returned by SHPOpen()
or SHPCreate().
- iShape: The entity number of the shape to read. Entity
+ iShape: The entity number of the shape to read. Entity
numbers are between 0 and nEntities-1 (as returned
by SHPGetInfo()).
</pre>
The SHPReadObject() call is used to read a single structure, or entity
from the shapefile. See the definition of the SHPObject structure for
detailed information on fields of a SHPObject. SHPObject's returned from
- SHPReadObject() should be deallocated with SHPDestroyShape().
+ SHPReadObject() should be deallocated with SHPDestroyShape().
SHPReadObject() will return NULL if an illegal iShape value is requested.<p>
Note that the bounds placed into the SHPObject are those read from the
<pre>
void SHPClose( SHPHandle hSHP );
- hSHP: The handle previously returned by SHPOpen()
+ hSHP: The handle previously returned by SHPOpen()
or SHPCreate().
</pre>
just be the path plus the basename of the pair.
nShapeType: The type of shapes to be stored in the newly created
- file. It may be either SHPT_POINT, SHPT_ARC,
+ file. It may be either SHPT_POINT, SHPT_ARC,
SHPT_POLYGON or SHPT_MULTIPOINT.
</pre>
<h2>SHPCreateSimpleObject()</h2>
<pre>
-SHPObject *
- SHPCreateSimpleObject( int nSHPType, int nVertices,
+SHPObject *
+ SHPCreateSimpleObject( int nSHPType, int nVertices,
double *padfX, double * padfY, double *padfZ, );
nSHPType: The SHPT_ type of the object to be created, such
as SHPT_POINT, or SHPT_POLYGON.
-
- nVertices: The number of vertices being passed in padfX,
- padfY, and padfZ.
+
+ nVertices: The number of vertices being passed in padfX,
+ padfY, and padfZ.
padfX: An array of nVertices X coordinates of the vertices
for this object.
they are all assumed to be zero.
</pre>
- The SHPCreateSimpleObject() allows for the convenient creation of
+ The SHPCreateSimpleObject() allows for the convenient creation of
simple objects. This is normally used so that the SHPObject can be
passed to SHPWriteObject() to write it to the file. The simple object
creation API assumes an M (measure) value of zero for each vertex. For
SHPDestroyObject() function should be used to free resources associated with
an object allocated with SHPCreateSimpleObject(). <p>
- This function computes a bounding box for the SHPObject from the given
+ This function computes a bounding box for the SHPObject from the given
vertices.<p>
<!-------------------------------------------------------------------------->
<h2>SHPCreateObject()</h2>
<pre>
-SHPObject *
+SHPObject *
SHPCreateObject( int nSHPType, int iShape,
int nParts, int * panPartStart, int * panPartType,
- int nVertices, double *padfX, double * padfY,
+ int nVertices, double *padfX, double * padfY,
double *padfZ, double *padfM );
nSHPType: The SHPT_ type of the object to be created, such
iShape: The shapeid to be recorded with this shape.
nParts: The number of parts for this object. If this is
- zero for ARC, or POLYGON type objects, a single
+ zero for ARC, or POLYGON type objects, a single
zero valued part will be created internally.
-
+
panPartStart: The list of zero based start vertices for the rings
(parts) in this object. The first should always be
zero. This may be NULL if nParts is 0.
-
+
panPartType: The type of each of the parts. This is only meaningful
for MULTIPATCH files. For all other cases this may
be NULL, and will be assumed to be SHPP_RING.
-
- nVertices: The number of vertices being passed in padfX,
- padfY, and padfZ.
+
+ nVertices: The number of vertices being passed in padfX,
+ padfY, and padfZ.
padfX: An array of nVertices X coordinates of the vertices
for this object.
for this object. This may be NULL in which case
they are all assumed to be zero.
- padfM: An array of nVertices M (measure values) of the
- vertices for this object. This may be NULL in which
+ padfM: An array of nVertices M (measure values) of the
+ vertices for this object. This may be NULL in which
case they are all assumed to be zero.
</pre>
- The SHPCreateSimpleObject() allows for the creation of objects (shapes).
- This is normally used so that the SHPObject can be passed to
+ The SHPCreateSimpleObject() allows for the creation of objects (shapes).
+ This is normally used so that the SHPObject can be passed to
SHPWriteObject() to write it to the file. <p>
- The SHPDestroyObject() function should be used to free resources associated
+ The SHPDestroyObject() function should be used to free resources associated
with an object allocated with SHPCreateObject(). <p>
- This function computes a bounding box for the SHPObject from the given
+ This function computes a bounding box for the SHPObject from the given
vertices.<p>
<!-------------------------------------------------------------------------->
psObject: An existing shape object to be updated in place.
</pre>
-
+
This function will recompute the extents of this shape, replacing the
- existing values of the dfXMin, dfYMin, dfZMin, dfMMin, dfXMax, dfYMax,
+ existing values of the dfXMin, dfYMin, dfZMin, dfMMin, dfXMax, dfYMax,
dfZMax, and dfMMax values based on the current set of vertices for the
shape. This function is automatically called by SHPCreateObject() but
if the vertices of an existing object are altered it should be called again
<pre>
int SHPWriteObject( SHPHandle hSHP, int iShape, SHPObject *psObject );
- hSHP: The handle previously returned by SHPOpen("r+")
+ hSHP: The handle previously returned by SHPOpen("r+")
or SHPCreate().
iShape: The entity number of the shape to write. A value of
- -1 should be used for new shapes.
+ -1 should be used for new shapes.
psObject: The shape to write to the file. This should have
- been created with SHPCreateObject(), or
+ been created with SHPCreateObject(), or
SHPCreateSimpleObject().
</pre>
This function will reverse any rings necessary in order to enforce the
shapefile restrictions on the required order of inner and outer rings in
the Shapefile specification. It returns TRUE if a change is made and FALSE
- if no change is made. Only polygon objects will be affected though any
+ if no change is made. Only polygon objects will be affected though any
object may be passed.
<p>
/******************************************************************************
- * $Id: shpopen.c,v 1.78 2019-02-28 15:55:23 erouault Exp $
*
* Project: Shapelib
* Purpose: Implementation of core Shapefile read/write functions.
*
******************************************************************************
* Copyright (c) 1999, 2001, Frank Warmerdam
- * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2011-2019, Even Rouault <even dot rouault at spatialys.com>
*
- * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see COPYING). This
- * option is discussed in more detail in shapelib.html.
- *
- * --
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- *
- * $Log: shpopen.c,v $
- * Revision 1.78 2019-02-28 15:55:23 erouault
- * * shpopen.c: resync with GDAL internal shapelib to avoid being dependent
- * on correctness of file size field in .shp. Fixes
- * https://lists.osgeo.org/pipermail/gdal-dev/2018-October/049218.html
- *
- * Revision 1.77 2018-08-16 15:39:07 erouault
- * * shpopen.c, dbfopen.c, shptree.c, sbnsearch.c: resyc with GDAL
- * internal shapelib. Mostly to allow building those files as C++
- * without warning. Also add FTDate entry in DBFFieldType
- * (see https://github.com/OSGeo/gdal/pull/308). And some other
- * code cleanups
- *
- * Revision 1.76 2017-09-10 10:11:36 erouault
- * * shpopen.c: resync with GDAL copy. Make sure to zero terminate all
- * error messages. And fix regression regarding re-writing the last shape
- * of a file (https://trac.osgeo.org/gdal/ticket/7031)
- *
- * Revision 1.75 2016-12-05 12:44:05 erouault
- * * Major overhaul of Makefile build system to use autoconf/automake.
- *
- * * Warning fixes in contrib/
- *
- * Revision 1.74 2016-12-04 15:30:15 erouault
- * * shpopen.c, dbfopen.c, shptree.c, shapefil.h: resync with
- * GDAL Shapefile driver. Mostly cleanups. SHPObject and DBFInfo
- * structures extended with new members. New functions:
- * DBFSetLastModifiedDate, SHPOpenLLEx, SHPRestoreSHX,
- * SHPSetFastModeReadObject
- *
- * * sbnsearch.c: new file to implement original ESRI .sbn spatial
- * index reading. (no write support). New functions:
- * SBNOpenDiskTree, SBNCloseDiskTree, SBNSearchDiskTree,
- * SBNSearchDiskTreeInteger, SBNSearchFreeIds
- *
- * * Makefile, makefile.vc, CMakeLists.txt, shapelib.def: updates
- * with new file and symbols.
- *
- * * commit: helper script to cvs commit
- *
- * Revision 1.73 2012-01-24 22:33:01 fwarmerdam
- * fix memory leak on failure to open .shp (gdal #4410)
- *
- * Revision 1.72 2011-12-11 22:45:28 fwarmerdam
- * fix failure return from SHPOpenLL.
- *
- * Revision 1.71 2011-09-15 03:33:58 fwarmerdam
- * fix missing cast (#2344)
- *
- * Revision 1.70 2011-07-24 05:59:25 fwarmerdam
- * minimize use of CPLError in favor of SAHooks.Error()
- *
- * Revision 1.69 2011-07-24 03:24:22 fwarmerdam
- * fix memory leaks in error cases creating shapefiles (#2061)
- *
- * Revision 1.68 2010-08-27 23:42:52 fwarmerdam
- * add SHPAPI_CALL attribute in code
- *
- * Revision 1.67 2010-07-01 08:15:48 fwarmerdam
- * do not error out on an object with zero vertices
- *
- * Revision 1.66 2010-07-01 07:58:57 fwarmerdam
- * minor cleanup of error handling
- *
- * Revision 1.65 2010-07-01 07:27:13 fwarmerdam
- * white space formatting adjustments
- *
- * Revision 1.64 2010-01-28 11:34:34 fwarmerdam
- * handle the shape file length limits more gracefully (#3236)
- *
- * Revision 1.63 2010-01-28 04:04:40 fwarmerdam
- * improve numerical accuracy of SHPRewind() algs (gdal #3363)
- *
- * Revision 1.62 2010-01-17 05:34:13 fwarmerdam
- * Remove asserts on x/y being null (#2148).
- *
- * Revision 1.61 2010-01-16 05:07:42 fwarmerdam
- * allow 0/nulls in shpcreateobject (#2148)
- *
- * Revision 1.60 2009-09-17 20:50:02 bram
- * on Win32, define snprintf as alias to _snprintf
- *
- * Revision 1.59 2008-03-14 05:25:31 fwarmerdam
- * Correct crash on buggy geometries (gdal #2218)
- *
- * Revision 1.58 2008/01/08 23:28:26 bram
- * on line 2095, use a float instead of a double to avoid a compiler warning
- *
- * Revision 1.57 2007/12/06 07:00:25 fwarmerdam
- * dbfopen now using SAHooks for fileio
- *
- * Revision 1.56 2007/12/04 20:37:56 fwarmerdam
- * preliminary implementation of hooks api for io and errors
- *
- * Revision 1.55 2007/11/21 22:39:56 fwarmerdam
- * close shx file in readonly mode (GDAL #1956)
- *
- * Revision 1.54 2007/11/15 00:12:47 mloskot
- * Backported recent changes from GDAL (Ticket #1415) to Shapelib.
- *
- * Revision 1.53 2007/11/14 22:31:08 fwarmerdam
- * checks after mallocs to detect for corrupted/voluntary broken shapefiles.
- * http://trac.osgeo.org/gdal/ticket/1991
- *
- * Revision 1.52 2007/06/21 15:58:33 fwarmerdam
- * fix for SHPRewindObject when rings touch at one vertex (gdal #976)
- *
- * Revision 1.51 2006/09/04 15:24:01 fwarmerdam
- * Fixed up log message for 1.49.
- *
- * Revision 1.50 2006/09/04 15:21:39 fwarmerdam
- * fix of last fix
- *
- * Revision 1.49 2006/09/04 15:21:00 fwarmerdam
- * MLoskot: Added stronger test of Shapefile reading failures, e.g. truncated
- * files. The problem was discovered by Tim Sutton and reported here
- * https://svn.qgis.org/trac/ticket/200
- *
- * Revision 1.48 2006/01/26 15:07:32 fwarmerdam
- * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
- *
- * Revision 1.47 2006/01/04 20:07:23 fwarmerdam
- * In SHPWriteObject() make sure that the record length is updated
- * when rewriting an existing record.
- *
- * Revision 1.46 2005/02/11 17:17:46 fwarmerdam
- * added panPartStart[0] validation
- *
- * Revision 1.45 2004/09/26 20:09:48 fwarmerdam
- * const correctness changes
- *
- * Revision 1.44 2003/12/29 00:18:39 fwarmerdam
- * added error checking for failed IO and optional CPL error reporting
- *
- * Revision 1.43 2003/12/01 16:20:08 warmerda
- * be careful of zero vertex shapes
- *
- * Revision 1.42 2003/12/01 14:58:27 warmerda
- * added degenerate object check in SHPRewindObject()
- *
- * Revision 1.41 2003/07/08 15:22:43 warmerda
- * avoid warning
- *
- * Revision 1.40 2003/04/21 18:30:37 warmerda
- * added header write/update public methods
- *
- * Revision 1.39 2002/08/26 06:46:56 warmerda
- * avoid c++ comments
- *
- * Revision 1.38 2002/05/07 16:43:39 warmerda
- * Removed debugging printf()
- *
- * Revision 1.37 2002/04/10 17:35:22 warmerda
- * fixed bug in ring reversal code
- *
- * Revision 1.36 2002/04/10 16:59:54 warmerda
- * added SHPRewindObject
- *
- * Revision 1.35 2001/12/07 15:10:44 warmerda
- * fix if .shx fails to open
- *
- * Revision 1.34 2001/11/01 16:29:55 warmerda
- * move pabyRec into SHPInfo for thread safety
- *
- * Revision 1.33 2001/07/03 12:18:15 warmerda
- * Improved cleanup if SHX not found, provided by Riccardo Cohen.
- *
- * Revision 1.32 2001/06/22 01:58:07 warmerda
- * be more careful about establishing initial bounds in face of NULL shapes
- *
- * Revision 1.31 2001/05/31 19:35:29 warmerda
- * added support for writing null shapes
- *
- * Revision 1.30 2001/05/28 12:46:29 warmerda
- * Add some checking on reasonableness of record count when opening.
- *
- * Revision 1.29 2001/05/23 13:36:52 warmerda
- * added use of SHPAPI_CALL
- *
- * Revision 1.28 2001/02/06 22:25:06 warmerda
- * fixed memory leaks when SHPOpen() fails
- *
- * Revision 1.27 2000/07/18 15:21:33 warmerda
- * added better enforcement of -1 for append in SHPWriteObject
- *
- * Revision 1.26 2000/02/16 16:03:51 warmerda
- * added null shape support
- *
- * Revision 1.25 1999/12/15 13:47:07 warmerda
- * Fixed record size settings in .shp file (was 4 words too long)
- * Added stdlib.h.
- *
- * Revision 1.24 1999/11/05 14:12:04 warmerda
- * updated license terms
- *
- * Revision 1.23 1999/07/27 00:53:46 warmerda
- * added support for rewriting shapes
- *
- * Revision 1.22 1999/06/11 19:19:11 warmerda
- * Cleanup pabyRec static buffer on SHPClose().
- *
- * Revision 1.21 1999/06/02 14:57:56 kshih
- * Remove unused variables
- *
- * Revision 1.20 1999/04/19 21:04:17 warmerda
- * Fixed syntax error.
- *
- * Revision 1.19 1999/04/19 21:01:57 warmerda
- * Force access string to binary in SHPOpen().
- *
- * Revision 1.18 1999/04/01 18:48:07 warmerda
- * Try upper case extensions if lower case doesn't work.
- *
- * Revision 1.17 1998/12/31 15:29:39 warmerda
- * Disable writing measure values to multipatch objects if
- * DISABLE_MULTIPATCH_MEASURE is defined.
- *
- * Revision 1.16 1998/12/16 05:14:33 warmerda
- * Added support to write MULTIPATCH. Fixed reading Z coordinate of
- * MULTIPATCH. Fixed record size written for all feature types.
- *
- * Revision 1.15 1998/12/03 16:35:29 warmerda
- * r+b is proper binary access string, not rb+.
- *
- * Revision 1.14 1998/12/03 15:47:56 warmerda
- * Fixed setting of nVertices in SHPCreateObject().
- *
- * Revision 1.13 1998/12/03 15:33:54 warmerda
- * Made SHPCalculateExtents() separately callable.
- *
- * Revision 1.12 1998/11/11 20:01:50 warmerda
- * Fixed bug writing ArcM/Z, and PolygonM/Z for big endian machines.
- *
- * Revision 1.11 1998/11/09 20:56:44 warmerda
- * Fixed up handling of file wide bounds.
- *
- * Revision 1.10 1998/11/09 20:18:51 warmerda
- * Converted to support 3D shapefiles, and use of SHPObject.
- *
- * Revision 1.9 1998/02/24 15:09:05 warmerda
- * Fixed memory leak.
- *
- * Revision 1.8 1997/12/04 15:40:29 warmerda
- * Fixed byte swapping of record number, and record length fields in the
- * .shp file.
- *
- * Revision 1.7 1995/10/21 03:15:58 warmerda
- * Added support for binary file access, the magic cookie 9997
- * and tried to improve the int32 selection logic for 16bit systems.
- *
- * Revision 1.6 1995/09/04 04:19:41 warmerda
- * Added fix for file bounds.
- *
- * Revision 1.5 1995/08/25 15:16:44 warmerda
- * Fixed a couple of problems with big endian systems ... one with bounds
- * and the other with multipart polygons.
- *
- * Revision 1.4 1995/08/24 18:10:17 warmerda
- * Switch to use SfRealloc() to avoid problems with pre-ANSI realloc()
- * functions (such as on the Sun).
- *
- * Revision 1.3 1995/08/23 02:23:15 warmerda
- * Added support for reading bounds, and fixed up problems in setting the
- * file wide bounds.
- *
- * Revision 1.2 1995/08/04 03:16:57 warmerda
- * Added header.
- *
- */
+ * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+ ******************************************************************************/
#include "shapefil.h"
-#include <math.h>
-#include <limits.h>
#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-SHP_CVSID("$Id: shpopen.c,v 1.78 2019-02-28 15:55:23 erouault Exp $")
-
-typedef unsigned char uchar;
-
-#if UINT_MAX == 65535
-typedef unsigned long int32;
-#else
-typedef unsigned int int32;
-#endif
#ifndef FALSE
-# define FALSE 0
-# define TRUE 1
+#define FALSE 0
+#define TRUE 1
#endif
-#define ByteCopy( a, b, c ) memcpy( b, a, c )
+#define ByteCopy(a, b, c) memcpy(b, a, c)
#ifndef MAX
-# define MIN(a,b) ((a<b) ? a : b)
-# define MAX(a,b) ((a>b) ? a : b)
+#define MIN(a, b) ((a < b) ? a : b)
+#define MAX(a, b) ((a > b) ? a : b)
#endif
#ifndef USE_CPL
#if defined(_MSC_VER)
-# if _MSC_VER < 1900
-# define snprintf _snprintf
-# endif
+#if _MSC_VER < 1900
+#define snprintf _snprintf
+#endif
#elif defined(WIN32) || defined(_WIN32)
-# ifndef snprintf
-# define snprintf _snprintf
-# endif
+#ifndef snprintf
+#define snprintf _snprintf
+#endif
#endif
#endif
#ifndef CPL_UNUSED
#if defined(__GNUC__) && __GNUC__ >= 4
-# define CPL_UNUSED __attribute((__unused__))
+#define CPL_UNUSED __attribute((__unused__))
#else
-# define CPL_UNUSED
+#define CPL_UNUSED
+#endif
#endif
-#endif
+#ifndef bBigEndian
#if defined(CPL_LSB)
-#define bBigEndian FALSE
+#define bBigEndian false
#elif defined(CPL_MSB)
-#define bBigEndian TRUE
+#define bBigEndian true
#else
-static int bBigEndian;
+#ifndef static_var_bBigEndian_defined
+#define static_var_bBigEndian_defined
+static bool bBigEndian = false;
+#endif
+#endif
#endif
#ifdef __cplusplus
-#define STATIC_CAST(type,x) static_cast<type>(x)
+#define STATIC_CAST(type, x) static_cast<type>(x)
#define SHPLIB_NULLPTR nullptr
#else
-#define STATIC_CAST(type,x) ((type)(x))
+#define STATIC_CAST(type, x) ((type)(x))
#define SHPLIB_NULLPTR NULL
#endif
/* Swap a 2, 4 or 8 byte word. */
/************************************************************************/
-static void SwapWord( int length, void * wordP )
-
+#ifndef SwapWord_defined
+#define SwapWord_defined
+static void SwapWord(int length, void *wordP)
{
- int i;
- uchar temp;
-
- for( i=0; i < length/2; i++ )
+ for (int i = 0; i < length / 2; i++)
{
- temp = STATIC_CAST(uchar*, wordP)[i];
- STATIC_CAST(uchar*, wordP)[i] = STATIC_CAST(uchar*, wordP)[length-i-1];
- STATIC_CAST(uchar*, wordP)[length-i-1] = temp;
+ const unsigned char temp = STATIC_CAST(unsigned char *, wordP)[i];
+ STATIC_CAST(unsigned char *, wordP)
+ [i] = STATIC_CAST(unsigned char *, wordP)[length - i - 1];
+ STATIC_CAST(unsigned char *, wordP)[length - i - 1] = temp;
}
}
-
-/************************************************************************/
-/* SfRealloc() */
-/* */
-/* A realloc cover function that will access a NULL pointer as */
-/* a valid input. */
-/************************************************************************/
-
-static void * SfRealloc( void * pMem, int nNewSize )
-
-{
- if( pMem == SHPLIB_NULLPTR )
- return malloc(nNewSize);
- else
- return realloc(pMem,nNewSize);
-}
+#endif
/************************************************************************/
/* SHPWriteHeader() */
/* */
-/* Write out a header for the .shp and .shx files as well as the */
-/* contents of the index (.shx) file. */
+/* Write out a header for the .shp and .shx files as well as the */
+/* contents of the index (.shx) file. */
/************************************************************************/
-void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
-
+void SHPAPI_CALL SHPWriteHeader(SHPHandle psSHP)
{
- uchar abyHeader[100] = { 0 };
- int i;
- int32 i32;
- double dValue;
- int32 *panSHX;
-
if (psSHP->fpSHX == SHPLIB_NULLPTR)
{
- psSHP->sHooks.Error( "SHPWriteHeader failed : SHX file is closed");
+ psSHP->sHooks.Error("SHPWriteHeader failed : SHX file is closed");
return;
}
-/* -------------------------------------------------------------------- */
-/* Prepare header block for .shp file. */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* Prepare header block for .shp file. */
+ /* -------------------------------------------------------------------- */
- abyHeader[2] = 0x27; /* magic cookie */
+ unsigned char abyHeader[100] = {0};
+ abyHeader[2] = 0x27; /* magic cookie */
abyHeader[3] = 0x0a;
- i32 = psSHP->nFileSize/2; /* file size */
- ByteCopy( &i32, abyHeader+24, 4 );
- if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+ uint32_t i32 = psSHP->nFileSize / 2; /* file size */
+ ByteCopy(&i32, abyHeader + 24, 4);
+ if (!bBigEndian)
+ SwapWord(4, abyHeader + 24);
- i32 = 1000; /* version */
- ByteCopy( &i32, abyHeader+28, 4 );
- if( bBigEndian ) SwapWord( 4, abyHeader+28 );
+ i32 = 1000; /* version */
+ ByteCopy(&i32, abyHeader + 28, 4);
+ if (bBigEndian)
+ SwapWord(4, abyHeader + 28);
- i32 = psSHP->nShapeType; /* shape type */
- ByteCopy( &i32, abyHeader+32, 4 );
- if( bBigEndian ) SwapWord( 4, abyHeader+32 );
+ i32 = psSHP->nShapeType; /* shape type */
+ ByteCopy(&i32, abyHeader + 32, 4);
+ if (bBigEndian)
+ SwapWord(4, abyHeader + 32);
- dValue = psSHP->adBoundsMin[0]; /* set bounds */
- ByteCopy( &dValue, abyHeader+36, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+36 );
+ double dValue = psSHP->adBoundsMin[0]; /* set bounds */
+ ByteCopy(&dValue, abyHeader + 36, 8);
+ if (bBigEndian)
+ SwapWord(8, abyHeader + 36);
dValue = psSHP->adBoundsMin[1];
- ByteCopy( &dValue, abyHeader+44, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+44 );
+ ByteCopy(&dValue, abyHeader + 44, 8);
+ if (bBigEndian)
+ SwapWord(8, abyHeader + 44);
dValue = psSHP->adBoundsMax[0];
- ByteCopy( &dValue, abyHeader+52, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+52 );
+ ByteCopy(&dValue, abyHeader + 52, 8);
+ if (bBigEndian)
+ SwapWord(8, abyHeader + 52);
dValue = psSHP->adBoundsMax[1];
- ByteCopy( &dValue, abyHeader+60, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+60 );
+ ByteCopy(&dValue, abyHeader + 60, 8);
+ if (bBigEndian)
+ SwapWord(8, abyHeader + 60);
- dValue = psSHP->adBoundsMin[2]; /* z */
- ByteCopy( &dValue, abyHeader+68, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+68 );
+ dValue = psSHP->adBoundsMin[2]; /* z */
+ ByteCopy(&dValue, abyHeader + 68, 8);
+ if (bBigEndian)
+ SwapWord(8, abyHeader + 68);
dValue = psSHP->adBoundsMax[2];
- ByteCopy( &dValue, abyHeader+76, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+76 );
+ ByteCopy(&dValue, abyHeader + 76, 8);
+ if (bBigEndian)
+ SwapWord(8, abyHeader + 76);
- dValue = psSHP->adBoundsMin[3]; /* m */
- ByteCopy( &dValue, abyHeader+84, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+84 );
+ dValue = psSHP->adBoundsMin[3]; /* m */
+ ByteCopy(&dValue, abyHeader + 84, 8);
+ if (bBigEndian)
+ SwapWord(8, abyHeader + 84);
dValue = psSHP->adBoundsMax[3];
- ByteCopy( &dValue, abyHeader+92, 8 );
- if( bBigEndian ) SwapWord( 8, abyHeader+92 );
+ ByteCopy(&dValue, abyHeader + 92, 8);
+ if (bBigEndian)
+ SwapWord(8, abyHeader + 92);
-/* -------------------------------------------------------------------- */
-/* Write .shp file header. */
-/* -------------------------------------------------------------------- */
- if( psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 0 ) != 0
- || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHP ) != 1 )
+ /* -------------------------------------------------------------------- */
+ /* Write .shp file header. */
+ /* -------------------------------------------------------------------- */
+ if (psSHP->sHooks.FSeek(psSHP->fpSHP, 0, 0) != 0 ||
+ psSHP->sHooks.FWrite(abyHeader, 100, 1, psSHP->fpSHP) != 1)
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Failure writing .shp header: %s", strerror(errno) );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Failure writing .shp header: %s", strerror(errno));
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
return;
}
-/* -------------------------------------------------------------------- */
-/* Prepare, and write .shx file header. */
-/* -------------------------------------------------------------------- */
- i32 = (psSHP->nRecords * 2 * sizeof(int32) + 100)/2; /* file size */
- ByteCopy( &i32, abyHeader+24, 4 );
- if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+ /* -------------------------------------------------------------------- */
+ /* Prepare, and write .shx file header. */
+ /* -------------------------------------------------------------------- */
+ i32 = (psSHP->nRecords * 2 * sizeof(uint32_t) + 100) / 2; /* file size */
+ ByteCopy(&i32, abyHeader + 24, 4);
+ if (!bBigEndian)
+ SwapWord(4, abyHeader + 24);
- if( psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 0 ) != 0
- || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHX ) != 1 )
+ if (psSHP->sHooks.FSeek(psSHP->fpSHX, 0, 0) != 0 ||
+ psSHP->sHooks.FWrite(abyHeader, 100, 1, psSHP->fpSHX) != 1)
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Failure writing .shx header: %s", strerror(errno) );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Failure writing .shx header: %s", strerror(errno));
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
return;
}
-/* -------------------------------------------------------------------- */
-/* Write out the .shx contents. */
-/* -------------------------------------------------------------------- */
- panSHX = STATIC_CAST(int32 *, malloc(sizeof(int32) * 2 * psSHP->nRecords));
- if( panSHX == SHPLIB_NULLPTR )
+ /* -------------------------------------------------------------------- */
+ /* Write out the .shx contents. */
+ /* -------------------------------------------------------------------- */
+ uint32_t *panSHX =
+ STATIC_CAST(uint32_t *, malloc(sizeof(uint32_t) * 2 * psSHP->nRecords));
+ if (panSHX == SHPLIB_NULLPTR)
{
- psSHP->sHooks.Error( "Failure allocatin panSHX" );
+ psSHP->sHooks.Error("Failure allocatin panSHX");
return;
}
- for( i = 0; i < psSHP->nRecords; i++ )
+ for (int i = 0; i < psSHP->nRecords; i++)
{
- panSHX[i*2 ] = psSHP->panRecOffset[i]/2;
- panSHX[i*2+1] = psSHP->panRecSize[i]/2;
- if( !bBigEndian ) SwapWord( 4, panSHX+i*2 );
- if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
+ panSHX[i * 2] = psSHP->panRecOffset[i] / 2;
+ panSHX[i * 2 + 1] = psSHP->panRecSize[i] / 2;
+ if (!bBigEndian)
+ SwapWord(4, panSHX + i * 2);
+ if (!bBigEndian)
+ SwapWord(4, panSHX + i * 2 + 1);
}
- if( STATIC_CAST(int, psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX ))
- != psSHP->nRecords )
+ if (STATIC_CAST(int, psSHP->sHooks.FWrite(panSHX, sizeof(uint32_t) * 2,
+ psSHP->nRecords, psSHP->fpSHX)) !=
+ psSHP->nRecords)
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Failure writing .shx contents: %s", strerror(errno) );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Failure writing .shx contents: %s", strerror(errno));
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
}
- free( panSHX );
+ free(panSHX);
-/* -------------------------------------------------------------------- */
-/* Flush to disk. */
-/* -------------------------------------------------------------------- */
- psSHP->sHooks.FFlush( psSHP->fpSHP );
- psSHP->sHooks.FFlush( psSHP->fpSHX );
+ /* -------------------------------------------------------------------- */
+ /* Flush to disk. */
+ /* -------------------------------------------------------------------- */
+ psSHP->sHooks.FFlush(psSHP->fpSHP);
+ psSHP->sHooks.FFlush(psSHP->fpSHX);
}
/************************************************************************/
/* SHPOpen() */
/************************************************************************/
-SHPHandle SHPAPI_CALL
-SHPOpen( const char * pszLayer, const char * pszAccess )
-
+SHPHandle SHPAPI_CALL SHPOpen(const char *pszLayer, const char *pszAccess)
{
SAHooks sHooks;
- SASetupDefaultHooks( &sHooks );
+ SASetupDefaultHooks(&sHooks);
- return SHPOpenLL( pszLayer, pszAccess, &sHooks );
+ return SHPOpenLL(pszLayer, pszAccess, &sHooks);
}
/************************************************************************/
/* SHPGetLenWithoutExtension() */
/************************************************************************/
-static int SHPGetLenWithoutExtension(const char* pszBasename)
+static int SHPGetLenWithoutExtension(const char *pszBasename)
{
- int i;
- int nLen = STATIC_CAST(int, strlen(pszBasename));
- for( i = nLen-1;
- i > 0 && pszBasename[i] != '/' && pszBasename[i] != '\\';
- i-- )
+ const int nLen = STATIC_CAST(int, strlen(pszBasename));
+ for (int i = nLen - 1;
+ i > 0 && pszBasename[i] != '/' && pszBasename[i] != '\\'; i--)
{
- if( pszBasename[i] == '.' )
+ if (pszBasename[i] == '.')
{
return i;
}
/* files or either file name. */
/************************************************************************/
-SHPHandle SHPAPI_CALL
-SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
-
+SHPHandle SHPAPI_CALL SHPOpenLL(const char *pszLayer, const char *pszAccess,
+ const SAHooks *psHooks)
{
- char *pszFullname;
- SHPHandle psSHP;
-
- uchar *pabyBuf;
- int i;
- double dValue;
- int bLazySHXLoading = FALSE;
- int nLenWithoutExtension;
-
-/* -------------------------------------------------------------------- */
-/* Ensure the access string is one of the legal ones. We */
-/* ensure the result string indicates binary to avoid common */
-/* problems on Windows. */
-/* -------------------------------------------------------------------- */
- if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
- || strcmp(pszAccess,"r+") == 0 )
+ /* -------------------------------------------------------------------- */
+ /* Ensure the access string is one of the legal ones. We */
+ /* ensure the result string indicates binary to avoid common */
+ /* problems on Windows. */
+ /* -------------------------------------------------------------------- */
+ bool bLazySHXLoading = false;
+ if (strcmp(pszAccess, "rb+") == 0 || strcmp(pszAccess, "r+b") == 0 ||
+ strcmp(pszAccess, "r+") == 0)
+ {
pszAccess = "r+b";
+ }
else
{
bLazySHXLoading = strchr(pszAccess, 'l') != SHPLIB_NULLPTR;
/* Establish the byte order on this machine. */
/* -------------------------------------------------------------------- */
#if !defined(bBigEndian)
- i = 1;
- if( *((uchar *) &i) == 1 )
- bBigEndian = FALSE;
- else
- bBigEndian = TRUE;
+ {
+ int i = 1;
+ if (*((unsigned char *)&i) == 1)
+ bBigEndian = false;
+ else
+ bBigEndian = true;
+ }
#endif
-/* -------------------------------------------------------------------- */
-/* Initialize the info structure. */
-/* -------------------------------------------------------------------- */
- psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo),1));
+ /* -------------------------------------------------------------------- */
+ /* Initialize the info structure. */
+ /* -------------------------------------------------------------------- */
+ SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo), 1));
psSHP->bUpdated = FALSE;
- memcpy( &(psSHP->sHooks), psHooks, sizeof(SAHooks) );
-
-/* -------------------------------------------------------------------- */
-/* Open the .shp and .shx files. Note that files pulled from */
-/* a PC to Unix with upper case filenames won't work! */
-/* -------------------------------------------------------------------- */
- nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
- pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+ memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));
+
+ /* -------------------------------------------------------------------- */
+ /* Open the .shp and .shx files. Note that files pulled from */
+ /* a PC to Unix with upper case filenames won't work! */
+ /* -------------------------------------------------------------------- */
+ const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
+ char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
memcpy(pszFullname, pszLayer, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
- psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
- if( psSHP->fpSHP == SHPLIB_NULLPTR )
+ psSHP->fpSHP =
+ psSHP->sHooks.FOpen(pszFullname, pszAccess, psSHP->sHooks.pvUserData);
+ if (psSHP->fpSHP == SHPLIB_NULLPTR)
{
memcpy(pszFullname + nLenWithoutExtension, ".SHP", 5);
- psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
+ psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess,
+ psSHP->sHooks.pvUserData);
}
- if( psSHP->fpSHP == SHPLIB_NULLPTR )
+ if (psSHP->fpSHP == SHPLIB_NULLPTR)
{
- size_t nMessageLen = strlen(pszFullname)*2+256;
+ const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
pszFullname[nLenWithoutExtension] = 0;
- snprintf( pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
- pszFullname, pszFullname );
- psHooks->Error( pszMessage );
- free( pszMessage );
+ snprintf(pszMessage, nMessageLen,
+ "Unable to open %s.shp or %s.SHP in %s mode.", pszFullname,
+ pszFullname, pszAccess);
+ psHooks->Error(pszMessage);
+ free(pszMessage);
- free( psSHP );
- free( pszFullname );
+ free(psSHP);
+ free(pszFullname);
return SHPLIB_NULLPTR;
}
memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
- psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
- if( psSHP->fpSHX == SHPLIB_NULLPTR )
+ psSHP->fpSHX =
+ psSHP->sHooks.FOpen(pszFullname, pszAccess, psSHP->sHooks.pvUserData);
+ if (psSHP->fpSHX == SHPLIB_NULLPTR)
{
memcpy(pszFullname + nLenWithoutExtension, ".SHX", 5);
- psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
+ psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess,
+ psSHP->sHooks.pvUserData);
}
- if( psSHP->fpSHX == SHPLIB_NULLPTR )
+ if (psSHP->fpSHX == SHPLIB_NULLPTR)
{
- size_t nMessageLen = strlen(pszFullname)*2+256;
+ const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
pszFullname[nLenWithoutExtension] = 0;
- snprintf( pszMessage, nMessageLen, "Unable to open %s.shx or %s.SHX. "
- "Set SHAPE_RESTORE_SHX config option to YES to restore or "
- "create it.", pszFullname, pszFullname );
- psHooks->Error( pszMessage );
- free( pszMessage );
-
- psSHP->sHooks.FClose( psSHP->fpSHP );
- free( psSHP );
- free( pszFullname );
- return SHPLIB_NULLPTR ;
+ snprintf(pszMessage, nMessageLen,
+ "Unable to open %s.shx or %s.SHX. "
+ "Set SHAPE_RESTORE_SHX config option to YES to restore or "
+ "create it.",
+ pszFullname, pszFullname);
+ psHooks->Error(pszMessage);
+ free(pszMessage);
+
+ psSHP->sHooks.FClose(psSHP->fpSHP);
+ free(psSHP);
+ free(pszFullname);
+ return SHPLIB_NULLPTR;
}
- free( pszFullname );
+ free(pszFullname);
-/* -------------------------------------------------------------------- */
-/* Read the file size from the SHP file. */
-/* -------------------------------------------------------------------- */
- pabyBuf = STATIC_CAST(uchar *, malloc(100));
- if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP ) != 1 )
+ /* -------------------------------------------------------------------- */
+ /* Read the file size from the SHP file. */
+ /* -------------------------------------------------------------------- */
+ unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(100));
+ if (psSHP->sHooks.FRead(pabyBuf, 100, 1, psSHP->fpSHP) != 1)
{
- psSHP->sHooks.Error( ".shp file is unreadable, or corrupt." );
- psSHP->sHooks.FClose( psSHP->fpSHP );
- psSHP->sHooks.FClose( psSHP->fpSHX );
- free( pabyBuf );
- free( psSHP );
+ psSHP->sHooks.Error(".shp file is unreadable, or corrupt.");
+ psSHP->sHooks.FClose(psSHP->fpSHP);
+ psSHP->sHooks.FClose(psSHP->fpSHX);
+ free(pabyBuf);
+ free(psSHP);
- return SHPLIB_NULLPTR ;
+ return SHPLIB_NULLPTR;
}
- psSHP->nFileSize = (STATIC_CAST(unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
- (pabyBuf[26]<<8)|pabyBuf[27];
- if( psSHP->nFileSize < UINT_MAX / 2 )
+ psSHP->nFileSize = (STATIC_CAST(unsigned int, pabyBuf[24]) << 24) |
+ (pabyBuf[25] << 16) | (pabyBuf[26] << 8) | pabyBuf[27];
+ if (psSHP->nFileSize < UINT_MAX / 2)
psSHP->nFileSize *= 2;
else
psSHP->nFileSize = (UINT_MAX / 2) * 2;
-/* -------------------------------------------------------------------- */
-/* Read SHX file Header info */
-/* -------------------------------------------------------------------- */
- if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHX ) != 1
- || pabyBuf[0] != 0
- || pabyBuf[1] != 0
- || pabyBuf[2] != 0x27
- || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
- {
- psSHP->sHooks.Error( ".shx file is unreadable, or corrupt." );
- psSHP->sHooks.FClose( psSHP->fpSHP );
- psSHP->sHooks.FClose( psSHP->fpSHX );
- free( pabyBuf );
- free( psSHP );
+ /* -------------------------------------------------------------------- */
+ /* Read SHX file Header info */
+ /* -------------------------------------------------------------------- */
+ if (psSHP->sHooks.FRead(pabyBuf, 100, 1, psSHP->fpSHX) != 1 ||
+ pabyBuf[0] != 0 || pabyBuf[1] != 0 || pabyBuf[2] != 0x27 ||
+ (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d))
+ {
+ psSHP->sHooks.Error(".shx file is unreadable, or corrupt.");
+ psSHP->sHooks.FClose(psSHP->fpSHP);
+ psSHP->sHooks.FClose(psSHP->fpSHX);
+ free(pabyBuf);
+ free(psSHP);
return SHPLIB_NULLPTR;
}
- psSHP->nRecords = pabyBuf[27]|(pabyBuf[26]<<8)|(pabyBuf[25]<<16)|
- ((pabyBuf[24] & 0x7F)<<24);
+ psSHP->nRecords = pabyBuf[27] | (pabyBuf[26] << 8) | (pabyBuf[25] << 16) |
+ ((pabyBuf[24] & 0x7F) << 24);
psSHP->nRecords = (psSHP->nRecords - 50) / 4;
psSHP->nShapeType = pabyBuf[32];
- if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
+ if (psSHP->nRecords < 0 || psSHP->nRecords > 256000000)
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Record count in .shp header is %d, which seems\n"
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Record count in .shx header is %d, which seems\n"
"unreasonable. Assuming header is corrupt.",
- psSHP->nRecords );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
- psSHP->sHooks.FClose( psSHP->fpSHP );
- psSHP->sHooks.FClose( psSHP->fpSHX );
- free( psSHP );
+ psSHP->nRecords);
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
+ psSHP->sHooks.FClose(psSHP->fpSHP);
+ psSHP->sHooks.FClose(psSHP->fpSHX);
+ free(psSHP);
free(pabyBuf);
return SHPLIB_NULLPTR;
/* If a lot of records are advertized, check that the file is big enough */
/* to hold them */
- if( psSHP->nRecords >= 1024 * 1024 )
+ if (psSHP->nRecords >= 1024 * 1024)
{
- SAOffset nFileSize;
- psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 2 );
- nFileSize = psSHP->sHooks.FTell( psSHP->fpSHX );
- if( nFileSize > 100 &&
- nFileSize/2 < STATIC_CAST(SAOffset, psSHP->nRecords * 4 + 50) )
+ psSHP->sHooks.FSeek(psSHP->fpSHX, 0, 2);
+ const SAOffset nFileSize = psSHP->sHooks.FTell(psSHP->fpSHX);
+ if (nFileSize > 100 &&
+ nFileSize / 2 < STATIC_CAST(SAOffset, psSHP->nRecords * 4 + 50))
{
psSHP->nRecords = STATIC_CAST(int, (nFileSize - 100) / 8);
}
- psSHP->sHooks.FSeek( psSHP->fpSHX, 100, 0 );
+ psSHP->sHooks.FSeek(psSHP->fpSHX, 100, 0);
}
-/* -------------------------------------------------------------------- */
-/* Read the bounds. */
-/* -------------------------------------------------------------------- */
- if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
- memcpy( &dValue, pabyBuf+36, 8 );
+ /* -------------------------------------------------------------------- */
+ /* Read the bounds. */
+ /* -------------------------------------------------------------------- */
+ double dValue;
+
+ if (bBigEndian)
+ SwapWord(8, pabyBuf + 36);
+ memcpy(&dValue, pabyBuf + 36, 8);
psSHP->adBoundsMin[0] = dValue;
- if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
- memcpy( &dValue, pabyBuf+44, 8 );
+ if (bBigEndian)
+ SwapWord(8, pabyBuf + 44);
+ memcpy(&dValue, pabyBuf + 44, 8);
psSHP->adBoundsMin[1] = dValue;
- if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
- memcpy( &dValue, pabyBuf+52, 8 );
+ if (bBigEndian)
+ SwapWord(8, pabyBuf + 52);
+ memcpy(&dValue, pabyBuf + 52, 8);
psSHP->adBoundsMax[0] = dValue;
- if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
- memcpy( &dValue, pabyBuf+60, 8 );
+ if (bBigEndian)
+ SwapWord(8, pabyBuf + 60);
+ memcpy(&dValue, pabyBuf + 60, 8);
psSHP->adBoundsMax[1] = dValue;
- if( bBigEndian ) SwapWord( 8, pabyBuf+68 ); /* z */
- memcpy( &dValue, pabyBuf+68, 8 );
+ if (bBigEndian)
+ SwapWord(8, pabyBuf + 68); /* z */
+ memcpy(&dValue, pabyBuf + 68, 8);
psSHP->adBoundsMin[2] = dValue;
- if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
- memcpy( &dValue, pabyBuf+76, 8 );
+ if (bBigEndian)
+ SwapWord(8, pabyBuf + 76);
+ memcpy(&dValue, pabyBuf + 76, 8);
psSHP->adBoundsMax[2] = dValue;
- if( bBigEndian ) SwapWord( 8, pabyBuf+84 ); /* z */
- memcpy( &dValue, pabyBuf+84, 8 );
+ if (bBigEndian)
+ SwapWord(8, pabyBuf + 84); /* z */
+ memcpy(&dValue, pabyBuf + 84, 8);
psSHP->adBoundsMin[3] = dValue;
- if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
- memcpy( &dValue, pabyBuf+92, 8 );
+ if (bBigEndian)
+ SwapWord(8, pabyBuf + 92);
+ memcpy(&dValue, pabyBuf + 92, 8);
psSHP->adBoundsMax[3] = dValue;
- free( pabyBuf );
+ free(pabyBuf);
-/* -------------------------------------------------------------------- */
-/* Read the .shx file to get the offsets to each record in */
-/* the .shp file. */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* Read the .shx file to get the offsets to each record in */
+ /* the .shp file. */
+ /* -------------------------------------------------------------------- */
psSHP->nMaxRecords = psSHP->nRecords;
- psSHP->panRecOffset = STATIC_CAST(unsigned int *,
- malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) ));
- psSHP->panRecSize = STATIC_CAST(unsigned int *,
- malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) ));
- if( bLazySHXLoading )
+ psSHP->panRecOffset =
+ STATIC_CAST(unsigned int *,
+ malloc(sizeof(unsigned int) * MAX(1, psSHP->nMaxRecords)));
+ psSHP->panRecSize =
+ STATIC_CAST(unsigned int *,
+ malloc(sizeof(unsigned int) * MAX(1, psSHP->nMaxRecords)));
+ if (bLazySHXLoading)
pabyBuf = SHPLIB_NULLPTR;
else
- pabyBuf = STATIC_CAST(uchar *, malloc(8 * MAX(1,psSHP->nRecords) ));
+ pabyBuf =
+ STATIC_CAST(unsigned char *, malloc(8 * MAX(1, psSHP->nRecords)));
if (psSHP->panRecOffset == SHPLIB_NULLPTR ||
psSHP->panRecSize == SHPLIB_NULLPTR ||
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Not enough memory to allocate requested memory (nRecords=%d).\n"
- "Probably broken SHP file",
- psSHP->nRecords );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
- psSHP->sHooks.FClose( psSHP->fpSHP );
- psSHP->sHooks.FClose( psSHP->fpSHX );
- if (psSHP->panRecOffset) free( psSHP->panRecOffset );
- if (psSHP->panRecSize) free( psSHP->panRecSize );
- if (pabyBuf) free( pabyBuf );
- free( psSHP );
+ snprintf(
+ szErrorMsg, sizeof(szErrorMsg),
+ "Not enough memory to allocate requested memory (nRecords=%d).\n"
+ "Probably broken SHP file",
+ psSHP->nRecords);
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
+ psSHP->sHooks.FClose(psSHP->fpSHP);
+ psSHP->sHooks.FClose(psSHP->fpSHX);
+ if (psSHP->panRecOffset)
+ free(psSHP->panRecOffset);
+ if (psSHP->panRecSize)
+ free(psSHP->panRecSize);
+ if (pabyBuf)
+ free(pabyBuf);
+ free(psSHP);
return SHPLIB_NULLPTR;
}
- if( bLazySHXLoading )
+ if (bLazySHXLoading)
{
- memset(psSHP->panRecOffset, 0, sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
- memset(psSHP->panRecSize, 0, sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
- free( pabyBuf ); // sometimes make cppcheck happy, but
- return( psSHP );
+ memset(psSHP->panRecOffset, 0,
+ sizeof(unsigned int) * MAX(1, psSHP->nMaxRecords));
+ memset(psSHP->panRecSize, 0,
+ sizeof(unsigned int) * MAX(1, psSHP->nMaxRecords));
+ free(pabyBuf); // sometimes make cppcheck happy, but
+ return (psSHP);
}
- if( STATIC_CAST(int, psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ))
- != psSHP->nRecords )
+ if (STATIC_CAST(int, psSHP->sHooks.FRead(pabyBuf, 8, psSHP->nRecords,
+ psSHP->fpSHX)) != psSHP->nRecords)
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
"Failed to read all values for %d records in .shx file: %s.",
- psSHP->nRecords, strerror(errno) );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ psSHP->nRecords, strerror(errno));
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
/* SHX is short or unreadable for some reason. */
- psSHP->sHooks.FClose( psSHP->fpSHP );
- psSHP->sHooks.FClose( psSHP->fpSHX );
- free( psSHP->panRecOffset );
- free( psSHP->panRecSize );
- free( pabyBuf );
- free( psSHP );
+ psSHP->sHooks.FClose(psSHP->fpSHP);
+ psSHP->sHooks.FClose(psSHP->fpSHX);
+ free(psSHP->panRecOffset);
+ free(psSHP->panRecSize);
+ free(pabyBuf);
+ free(psSHP);
return SHPLIB_NULLPTR;
}
/* In read-only mode, we can close the SHX now */
if (strcmp(pszAccess, "rb") == 0)
{
- psSHP->sHooks.FClose( psSHP->fpSHX );
+ psSHP->sHooks.FClose(psSHP->fpSHX);
psSHP->fpSHX = SHPLIB_NULLPTR;
}
- for( i = 0; i < psSHP->nRecords; i++ )
+ for (int i = 0; i < psSHP->nRecords; i++)
{
- unsigned int nOffset, nLength;
-
- memcpy( &nOffset, pabyBuf + i * 8, 4 );
- if( !bBigEndian ) SwapWord( 4, &nOffset );
+ unsigned int nOffset;
+ memcpy(&nOffset, pabyBuf + i * 8, 4);
+ if (!bBigEndian)
+ SwapWord(4, &nOffset);
- memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
- if( !bBigEndian ) SwapWord( 4, &nLength );
+ unsigned int nLength;
+ memcpy(&nLength, pabyBuf + i * 8 + 4, 4);
+ if (!bBigEndian)
+ SwapWord(4, &nLength);
- if( nOffset > STATIC_CAST(unsigned int, INT_MAX) )
+ if (nOffset > STATIC_CAST(unsigned int, INT_MAX))
{
char str[128];
- snprintf( str, sizeof(str),
- "Invalid offset for entity %d", i);
- str[sizeof(str)-1] = '\0';
+ snprintf(str, sizeof(str), "Invalid offset for entity %d", i);
+ str[sizeof(str) - 1] = '\0';
- psSHP->sHooks.Error( str );
+ psSHP->sHooks.Error(str);
SHPClose(psSHP);
- free( pabyBuf );
+ free(pabyBuf);
return SHPLIB_NULLPTR;
}
- if( nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4) )
+ if (nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4))
{
char str[128];
- snprintf( str, sizeof(str),
- "Invalid length for entity %d", i);
- str[sizeof(str)-1] = '\0';
+ snprintf(str, sizeof(str), "Invalid length for entity %d", i);
+ str[sizeof(str) - 1] = '\0';
- psSHP->sHooks.Error( str );
+ psSHP->sHooks.Error(str);
SHPClose(psSHP);
- free( pabyBuf );
+ free(pabyBuf);
return SHPLIB_NULLPTR;
}
- psSHP->panRecOffset[i] = nOffset*2;
- psSHP->panRecSize[i] = nLength*2;
+ psSHP->panRecOffset[i] = nOffset * 2;
+ psSHP->panRecSize[i] = nLength * 2;
}
- free( pabyBuf );
+ free(pabyBuf);
- return( psSHP );
+ return (psSHP);
}
/************************************************************************/
/* in case when bRestoreSHX equals true. */
/************************************************************************/
-SHPHandle SHPAPI_CALL
-SHPOpenLLEx( const char * pszLayer, const char * pszAccess, SAHooks *psHooks,
- int bRestoreSHX )
-
+SHPHandle SHPAPI_CALL SHPOpenLLEx(const char *pszLayer, const char *pszAccess,
+ const SAHooks *psHooks, int bRestoreSHX)
{
- if ( !bRestoreSHX ) return SHPOpenLL ( pszLayer, pszAccess, psHooks );
+ if (!bRestoreSHX)
+ return SHPOpenLL(pszLayer, pszAccess, psHooks);
else
{
- if ( SHPRestoreSHX ( pszLayer, pszAccess, psHooks ) )
+ if (SHPRestoreSHX(pszLayer, pszAccess, psHooks))
{
- return SHPOpenLL ( pszLayer, pszAccess, psHooks );
+ return SHPOpenLL(pszLayer, pszAccess, psHooks);
}
}
/* */
/************************************************************************/
-int SHPAPI_CALL
-SHPRestoreSHX ( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
-
+int SHPAPI_CALL SHPRestoreSHX(const char *pszLayer, const char *pszAccess,
+ const SAHooks *psHooks)
{
- char *pszFullname;
- SAFile fpSHP, fpSHX;
-
-
- uchar *pabyBuf;
- int nLenWithoutExtension;
- unsigned int nSHPFilesize;
-
- unsigned int nCurrentRecordOffset = 0;
- unsigned int nCurrentSHPOffset = 100;
- size_t nRealSHXContentSize = 100;
-
- const char pszSHXAccess[] = "w+b";
- char *pabySHXHeader;
- char abyReadedRecord[8];
- unsigned int niRecord = 0;
- unsigned int nRecordLength = 0;
- unsigned int nRecordOffset = 50;
-
-/* -------------------------------------------------------------------- */
-/* Ensure the access string is one of the legal ones. We */
-/* ensure the result string indicates binary to avoid common */
-/* problems on Windows. */
-/* -------------------------------------------------------------------- */
- if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
- || strcmp(pszAccess,"r+") == 0 )
+ /* -------------------------------------------------------------------- */
+ /* Ensure the access string is one of the legal ones. We */
+ /* ensure the result string indicates binary to avoid common */
+ /* problems on Windows. */
+ /* -------------------------------------------------------------------- */
+ if (strcmp(pszAccess, "rb+") == 0 || strcmp(pszAccess, "r+b") == 0 ||
+ strcmp(pszAccess, "r+") == 0)
+ {
pszAccess = "r+b";
+ }
else
{
pszAccess = "rb";
#if !defined(bBigEndian)
{
int i = 1;
- if( *((uchar *) &i) == 1 )
- bBigEndian = FALSE;
+ if (*((unsigned char *)&i) == 1)
+ bBigEndian = false;
else
- bBigEndian = TRUE;
+ bBigEndian = true;
}
#endif
-/* -------------------------------------------------------------------- */
-/* Open the .shp file. Note that files pulled from */
-/* a PC to Unix with upper case filenames won't work! */
-/* -------------------------------------------------------------------- */
- nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
- pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+ /* -------------------------------------------------------------------- */
+ /* Open the .shp file. Note that files pulled from */
+ /* a PC to Unix with upper case filenames won't work! */
+ /* -------------------------------------------------------------------- */
+ const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
+ char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
memcpy(pszFullname, pszLayer, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
- fpSHP = psHooks->FOpen(pszFullname, pszAccess );
- if( fpSHP == SHPLIB_NULLPTR )
+ SAFile fpSHP = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData);
+ if (fpSHP == SHPLIB_NULLPTR)
{
memcpy(pszFullname + nLenWithoutExtension, ".SHP", 5);
- fpSHP = psHooks->FOpen(pszFullname, pszAccess );
+ fpSHP = psHooks->FOpen(pszFullname, pszAccess, psHooks->pvUserData);
}
- if( fpSHP == SHPLIB_NULLPTR )
+ if (fpSHP == SHPLIB_NULLPTR)
{
- size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
- char* pszMessage = STATIC_CAST(char *, malloc( nMessageLen ));
+ const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
+ char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
pszFullname[nLenWithoutExtension] = 0;
- snprintf( pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
- pszFullname, pszFullname );
- psHooks->Error( pszMessage );
- free( pszMessage );
+ snprintf(pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
+ pszFullname, pszFullname);
+ psHooks->Error(pszMessage);
+ free(pszMessage);
- free( pszFullname );
+ free(pszFullname);
- return( 0 );
+ return (0);
}
-/* -------------------------------------------------------------------- */
-/* Read the file size from the SHP file. */
-/* -------------------------------------------------------------------- */
- pabyBuf = STATIC_CAST(uchar *, malloc(100));
- psHooks->FRead( pabyBuf, 100, 1, fpSHP );
+ /* -------------------------------------------------------------------- */
+ /* Read the file size from the SHP file. */
+ /* -------------------------------------------------------------------- */
+ unsigned char *pabyBuf = STATIC_CAST(unsigned char *, malloc(100));
+ if (psHooks->FRead(pabyBuf, 100, 1, fpSHP) != 1)
+ {
+ psHooks->Error(".shp file is unreadable, or corrupt.");
+ psHooks->FClose(fpSHP);
- nSHPFilesize = (STATIC_CAST(unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
- (pabyBuf[26]<<8)|pabyBuf[27];
- if( nSHPFilesize < UINT_MAX / 2 )
+ free(pabyBuf);
+ free(pszFullname);
+
+ return (0);
+ }
+
+ unsigned int nSHPFilesize = (STATIC_CAST(unsigned int, pabyBuf[24]) << 24) |
+ (pabyBuf[25] << 16) | (pabyBuf[26] << 8) |
+ pabyBuf[27];
+ if (nSHPFilesize < UINT_MAX / 2)
nSHPFilesize *= 2;
else
nSHPFilesize = (UINT_MAX / 2) * 2;
memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
- fpSHX = psHooks->FOpen( pszFullname, pszSHXAccess );
- if( fpSHX == SHPLIB_NULLPTR )
- {
- memcpy(pszFullname + nLenWithoutExtension, ".SHX", 5);
- fpSHP = psHooks->FOpen(pszFullname, pszAccess );
- }
-
- if( fpSHX == SHPLIB_NULLPTR )
+ const char pszSHXAccess[] = "w+b";
+ SAFile fpSHX =
+ psHooks->FOpen(pszFullname, pszSHXAccess, psHooks->pvUserData);
+ if (fpSHX == SHPLIB_NULLPTR)
{
- size_t nMessageLen = strlen( pszFullname ) * 2 + 256;
- char* pszMessage = STATIC_CAST(char *, malloc( nMessageLen ));
+ size_t nMessageLen = strlen(pszFullname) * 2 + 256;
+ char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
pszFullname[nLenWithoutExtension] = 0;
- snprintf( pszMessage, nMessageLen,
- "Error opening file %s.shx or %s.SHX for writing",
- pszFullname, pszFullname );
- psHooks->Error( pszMessage );
- free( pszMessage );
+ snprintf(pszMessage, nMessageLen,
+ "Error opening file %s.shx for writing", pszFullname);
+ psHooks->Error(pszMessage);
+ free(pszMessage);
- psHooks->FClose( fpSHX );
+ psHooks->FClose(fpSHP);
- free( pabyBuf );
- free( pszFullname );
+ free(pabyBuf);
+ free(pszFullname);
- return( 0 );
+ return (0);
}
-/* -------------------------------------------------------------------- */
-/* Open SHX and create it using SHP file content. */
-/* -------------------------------------------------------------------- */
- psHooks->FSeek( fpSHP, 100, 0 );
- pabySHXHeader = STATIC_CAST(char *, malloc ( 100 ));
- memcpy( pabySHXHeader, pabyBuf, 100 );
- psHooks->FWrite( pabySHXHeader, 100, 1, fpSHX );
+ /* -------------------------------------------------------------------- */
+ /* Open SHX and create it using SHP file content. */
+ /* -------------------------------------------------------------------- */
+ psHooks->FSeek(fpSHP, 100, 0);
+ char *pabySHXHeader = STATIC_CAST(char *, malloc(100));
+ memcpy(pabySHXHeader, pabyBuf, 100);
+ psHooks->FWrite(pabySHXHeader, 100, 1, fpSHX);
+ free(pabyBuf);
+
+ // unsigned int nCurrentRecordOffset = 0;
+ unsigned int nCurrentSHPOffset = 100;
+ unsigned int nRealSHXContentSize = 100;
+ int nRetCode = TRUE;
+ unsigned int nRecordOffset = 50;
- while( nCurrentSHPOffset < nSHPFilesize )
+ while (nCurrentSHPOffset < nSHPFilesize)
{
- if( psHooks->FRead( &niRecord, 4, 1, fpSHP ) == 1 &&
- psHooks->FRead( &nRecordLength, 4, 1, fpSHP ) == 1)
+ unsigned int niRecord = 0;
+ unsigned int nRecordLength = 0;
+ int nSHPType;
+
+ if (psHooks->FRead(&niRecord, 4, 1, fpSHP) == 1 &&
+ psHooks->FRead(&nRecordLength, 4, 1, fpSHP) == 1 &&
+ psHooks->FRead(&nSHPType, 4, 1, fpSHP) == 1)
{
- if( !bBigEndian ) SwapWord( 4, &nRecordOffset );
- memcpy( abyReadedRecord, &nRecordOffset, 4 );
- memcpy( abyReadedRecord + 4, &nRecordLength, 4 );
+ char abyReadRecord[8];
+ unsigned int nRecordOffsetBE = nRecordOffset;
- psHooks->FWrite( abyReadedRecord, 8, 1, fpSHX );
+ if (!bBigEndian)
+ SwapWord(4, &nRecordOffsetBE);
+ memcpy(abyReadRecord, &nRecordOffsetBE, 4);
+ memcpy(abyReadRecord + 4, &nRecordLength, 4);
+
+ if (!bBigEndian)
+ SwapWord(4, &nRecordLength);
+
+ if (bBigEndian)
+ SwapWord(4, &nSHPType);
+
+ // Sanity check on record length
+ if (nRecordLength < 1 ||
+ nRecordLength > (nSHPFilesize - (nCurrentSHPOffset + 8)) / 2)
+ {
+ char szErrorMsg[200];
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Error parsing .shp to restore .shx. "
+ "Invalid record length = %u at record starting at "
+ "offset %u",
+ nSHPType, nCurrentSHPOffset);
+ psHooks->Error(szErrorMsg);
+
+ nRetCode = FALSE;
+ break;
+ }
+
+ // Sanity check on record type
+ if (nSHPType != SHPT_NULL && nSHPType != SHPT_POINT &&
+ nSHPType != SHPT_ARC && nSHPType != SHPT_POLYGON &&
+ nSHPType != SHPT_MULTIPOINT && nSHPType != SHPT_POINTZ &&
+ nSHPType != SHPT_ARCZ && nSHPType != SHPT_POLYGONZ &&
+ nSHPType != SHPT_MULTIPOINTZ && nSHPType != SHPT_POINTM &&
+ nSHPType != SHPT_ARCM && nSHPType != SHPT_POLYGONM &&
+ nSHPType != SHPT_MULTIPOINTM && nSHPType != SHPT_MULTIPATCH)
+ {
+ char szErrorMsg[200];
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Error parsing .shp to restore .shx. "
+ "Invalid shape type = %d at record starting at "
+ "offset %u",
+ nSHPType, nCurrentSHPOffset);
+ psHooks->Error(szErrorMsg);
+
+ nRetCode = FALSE;
+ break;
+ }
+
+ psHooks->FWrite(abyReadRecord, 8, 1, fpSHX);
- if ( !bBigEndian ) SwapWord( 4, &nRecordOffset );
- if ( !bBigEndian ) SwapWord( 4, &nRecordLength );
nRecordOffset += nRecordLength + 4;
- nCurrentRecordOffset += 8;
+ // nCurrentRecordOffset += 8;
nCurrentSHPOffset += 8 + nRecordLength * 2;
- psHooks->FSeek( fpSHP, nCurrentSHPOffset, 0 );
+ psHooks->FSeek(fpSHP, nCurrentSHPOffset, 0);
nRealSHXContentSize += 8;
}
else
{
- psHooks->Error( "Error parsing .shp to restore .shx" );
-
- psHooks->FClose( fpSHX );
- psHooks->FClose( fpSHP );
-
- free( pabySHXHeader );
- free( pszFullname );
+ char szErrorMsg[200];
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Error parsing .shp to restore .shx. "
+ "Cannot read first bytes of record starting at "
+ "offset %u",
+ nCurrentSHPOffset);
+ psHooks->Error(szErrorMsg);
- return( 0 );
+ nRetCode = FALSE;
+ break;
}
}
+ if (nRetCode && nCurrentSHPOffset != nSHPFilesize)
+ {
+ psHooks->Error("Error parsing .shp to restore .shx. "
+ "Not expected number of bytes");
+
+ nRetCode = FALSE;
+ }
- nRealSHXContentSize /= 2; // Bytes counted -> WORDs
- if( !bBigEndian ) SwapWord( 4, &nRealSHXContentSize );
- psHooks->FSeek( fpSHX, 24, 0 );
- psHooks->FWrite( &nRealSHXContentSize, 4, 1, fpSHX );
+ nRealSHXContentSize /= 2; // Bytes counted -> WORDs
+ if (!bBigEndian)
+ SwapWord(4, &nRealSHXContentSize);
+ psHooks->FSeek(fpSHX, 24, 0);
+ psHooks->FWrite(&nRealSHXContentSize, 4, 1, fpSHX);
- psHooks->FClose( fpSHP );
- psHooks->FClose( fpSHX );
+ psHooks->FClose(fpSHP);
+ psHooks->FClose(fpSHX);
- free ( pabyBuf );
- free ( pszFullname );
- free ( pabySHXHeader );
+ free(pszFullname);
+ free(pabySHXHeader);
- return( 1 );
+ return nRetCode;
}
/************************************************************************/
/* SHPClose() */
-/* */
-/* Close the .shp and .shx files. */
+/* */
+/* Close the .shp and .shx files. */
/************************************************************************/
-void SHPAPI_CALL
-SHPClose(SHPHandle psSHP )
-
+void SHPAPI_CALL SHPClose(SHPHandle psSHP)
{
- if( psSHP == SHPLIB_NULLPTR )
+ if (psSHP == SHPLIB_NULLPTR)
return;
-/* -------------------------------------------------------------------- */
-/* Update the header if we have modified anything. */
-/* -------------------------------------------------------------------- */
- if( psSHP->bUpdated )
- SHPWriteHeader( psSHP );
+ /* -------------------------------------------------------------------- */
+ /* Update the header if we have modified anything. */
+ /* -------------------------------------------------------------------- */
+ if (psSHP->bUpdated)
+ SHPWriteHeader(psSHP);
-/* -------------------------------------------------------------------- */
-/* Free all resources, and close files. */
-/* -------------------------------------------------------------------- */
- free( psSHP->panRecOffset );
- free( psSHP->panRecSize );
+ /* -------------------------------------------------------------------- */
+ /* Free all resources, and close files. */
+ /* -------------------------------------------------------------------- */
+ free(psSHP->panRecOffset);
+ free(psSHP->panRecSize);
- if ( psSHP->fpSHX != SHPLIB_NULLPTR)
- psSHP->sHooks.FClose( psSHP->fpSHX );
- psSHP->sHooks.FClose( psSHP->fpSHP );
+ if (psSHP->fpSHX != SHPLIB_NULLPTR)
+ psSHP->sHooks.FClose(psSHP->fpSHX);
+ psSHP->sHooks.FClose(psSHP->fpSHP);
- if( psSHP->pabyRec != SHPLIB_NULLPTR )
+ if (psSHP->pabyRec != SHPLIB_NULLPTR)
{
- free( psSHP->pabyRec );
+ free(psSHP->pabyRec);
}
- if( psSHP->pabyObjectBuf != SHPLIB_NULLPTR )
+ if (psSHP->pabyObjectBuf != SHPLIB_NULLPTR)
{
- free( psSHP->pabyObjectBuf );
+ free(psSHP->pabyObjectBuf);
}
- if( psSHP->psCachedObject != SHPLIB_NULLPTR )
+ if (psSHP->psCachedObject != SHPLIB_NULLPTR)
{
- free( psSHP->psCachedObject );
+ free(psSHP->psCachedObject);
}
- free( psSHP );
+ free(psSHP);
}
/************************************************************************/
/* So you cannot have 2 valid instances of SHPReadObject() simultaneously. */
/* The SHPObject padfZ and padfM members may be NULL depending on the geometry */
/* type. It is illegal to free at hand any of the pointer members of the SHPObject structure */
-void SHPAPI_CALL SHPSetFastModeReadObject( SHPHandle hSHP, int bFastMode )
+void SHPAPI_CALL SHPSetFastModeReadObject(SHPHandle hSHP, int bFastMode)
{
- if( bFastMode )
+ if (bFastMode)
{
- if( hSHP->psCachedObject == SHPLIB_NULLPTR )
+ if (hSHP->psCachedObject == SHPLIB_NULLPTR)
{
- hSHP->psCachedObject = STATIC_CAST(SHPObject*, calloc(1, sizeof(SHPObject)));
- assert( hSHP->psCachedObject != SHPLIB_NULLPTR );
+ hSHP->psCachedObject =
+ STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject)));
+ assert(hSHP->psCachedObject != SHPLIB_NULLPTR);
}
}
/* Fetch general information about the shape file. */
/************************************************************************/
-void SHPAPI_CALL
-SHPGetInfo(SHPHandle psSHP, int * pnEntities, int * pnShapeType,
- double * padfMinBound, double * padfMaxBound )
-
+void SHPAPI_CALL SHPGetInfo(SHPHandle psSHP, int *pnEntities, int *pnShapeType,
+ double *padfMinBound, double *padfMaxBound)
{
- int i;
-
- if( psSHP == SHPLIB_NULLPTR )
+ if (psSHP == SHPLIB_NULLPTR)
return;
- if( pnEntities != SHPLIB_NULLPTR )
+ if (pnEntities != SHPLIB_NULLPTR)
*pnEntities = psSHP->nRecords;
- if( pnShapeType != SHPLIB_NULLPTR )
+ if (pnShapeType != SHPLIB_NULLPTR)
*pnShapeType = psSHP->nShapeType;
- for( i = 0; i < 4; i++ )
+ for (int i = 0; i < 4; i++)
{
- if( padfMinBound != SHPLIB_NULLPTR )
+ if (padfMinBound != SHPLIB_NULLPTR)
padfMinBound[i] = psSHP->adBoundsMin[i];
- if( padfMaxBound != SHPLIB_NULLPTR )
+ if (padfMaxBound != SHPLIB_NULLPTR)
padfMaxBound[i] = psSHP->adBoundsMax[i];
}
}
/* shape file with read/write access. */
/************************************************************************/
-SHPHandle SHPAPI_CALL
-SHPCreate( const char * pszLayer, int nShapeType )
-
+SHPHandle SHPAPI_CALL SHPCreate(const char *pszLayer, int nShapeType)
{
SAHooks sHooks;
- SASetupDefaultHooks( &sHooks );
+ SASetupDefaultHooks(&sHooks);
- return SHPCreateLL( pszLayer, nShapeType, &sHooks );
+ return SHPCreateLL(pszLayer, nShapeType, &sHooks);
}
/************************************************************************/
/* shape file with read/write access. */
/************************************************************************/
-SHPHandle SHPAPI_CALL
-SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
-
+SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
+ const SAHooks *psHooks)
{
- char *pszFullname;
- SAFile fpSHP;
- SAFile fpSHX = SHPLIB_NULLPTR;
- uchar abyHeader[100];
- int32 i32;
- double dValue;
- int nLenWithoutExtension;
-
/* -------------------------------------------------------------------- */
/* Establish the byte order on this system. */
/* -------------------------------------------------------------------- */
#if !defined(bBigEndian)
{
int i = 1;
- if( *((uchar *) &i) == 1 )
- bBigEndian = FALSE;
+ if (*((unsigned char *)&i) == 1)
+ bBigEndian = false;
else
- bBigEndian = TRUE;
+ bBigEndian = true;
}
#endif
-/* -------------------------------------------------------------------- */
-/* Open the two files so we can write their headers. */
-/* -------------------------------------------------------------------- */
- nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
- pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
+ /* -------------------------------------------------------------------- */
+ /* Open the two files so we can write their headers. */
+ /* -------------------------------------------------------------------- */
+ const int nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
+ char *pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
memcpy(pszFullname, pszLayer, nLenWithoutExtension);
memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
- fpSHP = psHooks->FOpen(pszFullname, "wb" );
- if( fpSHP == SHPLIB_NULLPTR )
+ SAFile fpSHP = psHooks->FOpen(pszFullname, "w+b", psHooks->pvUserData);
+ if (fpSHP == SHPLIB_NULLPTR)
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Failed to create file %s: %s",
- pszFullname, strerror(errno) );
- psHooks->Error( szErrorMsg );
+ snprintf(szErrorMsg, sizeof(szErrorMsg), "Failed to create file %s: %s",
+ pszFullname, strerror(errno));
+ psHooks->Error(szErrorMsg);
- goto error;
+ free(pszFullname);
+ return NULL;
}
memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
- fpSHX = psHooks->FOpen(pszFullname, "wb" );
- if( fpSHX == SHPLIB_NULLPTR )
+ SAFile fpSHX = psHooks->FOpen(pszFullname, "w+b", psHooks->pvUserData);
+ if (fpSHX == SHPLIB_NULLPTR)
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Failed to create file %s: %s",
- pszFullname, strerror(errno) );
- psHooks->Error( szErrorMsg );
- goto error;
+ snprintf(szErrorMsg, sizeof(szErrorMsg), "Failed to create file %s: %s",
+ pszFullname, strerror(errno));
+ psHooks->Error(szErrorMsg);
+
+ free(pszFullname);
+ psHooks->FClose(fpSHP);
+ return NULL;
}
- free( pszFullname ); pszFullname = SHPLIB_NULLPTR;
+ free(pszFullname);
+ pszFullname = SHPLIB_NULLPTR;
-/* -------------------------------------------------------------------- */
-/* Prepare header block for .shp file. */
-/* -------------------------------------------------------------------- */
- memset( abyHeader, 0, sizeof(abyHeader) );
+ /* -------------------------------------------------------------------- */
+ /* Prepare header block for .shp file. */
+ /* -------------------------------------------------------------------- */
+ unsigned char abyHeader[100];
+ memset(abyHeader, 0, sizeof(abyHeader));
- abyHeader[2] = 0x27; /* magic cookie */
+ abyHeader[2] = 0x27; /* magic cookie */
abyHeader[3] = 0x0a;
- i32 = 50; /* file size */
- ByteCopy( &i32, abyHeader+24, 4 );
- if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+ uint32_t i32 = 50; /* file size */
+ ByteCopy(&i32, abyHeader + 24, 4);
+ if (!bBigEndian)
+ SwapWord(4, abyHeader + 24);
- i32 = 1000; /* version */
- ByteCopy( &i32, abyHeader+28, 4 );
- if( bBigEndian ) SwapWord( 4, abyHeader+28 );
+ i32 = 1000; /* version */
+ ByteCopy(&i32, abyHeader + 28, 4);
+ if (bBigEndian)
+ SwapWord(4, abyHeader + 28);
- i32 = nShapeType; /* shape type */
- ByteCopy( &i32, abyHeader+32, 4 );
- if( bBigEndian ) SwapWord( 4, abyHeader+32 );
+ i32 = nShapeType; /* shape type */
+ ByteCopy(&i32, abyHeader + 32, 4);
+ if (bBigEndian)
+ SwapWord(4, abyHeader + 32);
- dValue = 0.0; /* set bounds */
- ByteCopy( &dValue, abyHeader+36, 8 );
- ByteCopy( &dValue, abyHeader+44, 8 );
- ByteCopy( &dValue, abyHeader+52, 8 );
- ByteCopy( &dValue, abyHeader+60, 8 );
+ double dValue = 0.0; /* set bounds */
+ ByteCopy(&dValue, abyHeader + 36, 8);
+ ByteCopy(&dValue, abyHeader + 44, 8);
+ ByteCopy(&dValue, abyHeader + 52, 8);
+ ByteCopy(&dValue, abyHeader + 60, 8);
-/* -------------------------------------------------------------------- */
-/* Write .shp file header. */
-/* -------------------------------------------------------------------- */
- if( psHooks->FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
+ /* -------------------------------------------------------------------- */
+ /* Write .shp file header. */
+ /* -------------------------------------------------------------------- */
+ if (psHooks->FWrite(abyHeader, 100, 1, fpSHP) != 1)
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Failed to write .shp header: %s", strerror(errno) );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psHooks->Error( szErrorMsg );
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Failed to write .shp header: %s", strerror(errno));
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psHooks->Error(szErrorMsg);
- goto error;
+ free(pszFullname);
+ psHooks->FClose(fpSHP);
+ psHooks->FClose(fpSHX);
+ return NULL;
}
-/* -------------------------------------------------------------------- */
-/* Prepare, and write .shx file header. */
-/* -------------------------------------------------------------------- */
- i32 = 50; /* file size */
- ByteCopy( &i32, abyHeader+24, 4 );
- if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
+ /* -------------------------------------------------------------------- */
+ /* Prepare, and write .shx file header. */
+ /* -------------------------------------------------------------------- */
+ i32 = 50; /* file size */
+ ByteCopy(&i32, abyHeader + 24, 4);
+ if (!bBigEndian)
+ SwapWord(4, abyHeader + 24);
- if( psHooks->FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
+ if (psHooks->FWrite(abyHeader, 100, 1, fpSHX) != 1)
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Failure writing .shx header: %s", strerror(errno) );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psHooks->Error( szErrorMsg );
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Failure writing .shx header: %s", strerror(errno));
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psHooks->Error(szErrorMsg);
- goto error;
+ free(pszFullname);
+ psHooks->FClose(fpSHP);
+ psHooks->FClose(fpSHX);
+ return NULL;
}
-/* -------------------------------------------------------------------- */
-/* Close the files, and then open them as regular existing files. */
-/* -------------------------------------------------------------------- */
- psHooks->FClose( fpSHP );
- psHooks->FClose( fpSHX );
+ SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo), 1));
+
+ psSHP->bUpdated = FALSE;
+ memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));
- return( SHPOpenLL( pszLayer, "r+b", psHooks ) );
+ psSHP->fpSHP = fpSHP;
+ psSHP->fpSHX = fpSHX;
+ psSHP->nShapeType = nShapeType;
+ psSHP->nFileSize = 100;
+ psSHP->panRecOffset =
+ STATIC_CAST(unsigned int *, malloc(sizeof(unsigned int)));
+ psSHP->panRecSize =
+ STATIC_CAST(unsigned int *, malloc(sizeof(unsigned int)));
-error:
- if (pszFullname) free(pszFullname);
- if (fpSHP) psHooks->FClose( fpSHP );
- if (fpSHX) psHooks->FClose( fpSHX );
- return SHPLIB_NULLPTR;
+ if (psSHP->panRecOffset == SHPLIB_NULLPTR ||
+ psSHP->panRecSize == SHPLIB_NULLPTR)
+ {
+ psSHP->sHooks.Error("Not enough memory to allocate requested memory");
+ psSHP->sHooks.FClose(psSHP->fpSHP);
+ psSHP->sHooks.FClose(psSHP->fpSHX);
+ if (psSHP->panRecOffset)
+ free(psSHP->panRecOffset);
+ if (psSHP->panRecSize)
+ free(psSHP->panRecSize);
+ free(psSHP);
+ return SHPLIB_NULLPTR;
+ }
+
+ return psSHP;
}
/************************************************************************/
/* indicated location in the record. */
/************************************************************************/
-static void _SHPSetBounds( uchar * pabyRec, SHPObject * psShape )
-
+static void _SHPSetBounds(unsigned char *pabyRec, const SHPObject *psShape)
{
- ByteCopy( &(psShape->dfXMin), pabyRec + 0, 8 );
- ByteCopy( &(psShape->dfYMin), pabyRec + 8, 8 );
- ByteCopy( &(psShape->dfXMax), pabyRec + 16, 8 );
- ByteCopy( &(psShape->dfYMax), pabyRec + 24, 8 );
+ ByteCopy(&(psShape->dfXMin), pabyRec + 0, 8);
+ ByteCopy(&(psShape->dfYMin), pabyRec + 8, 8);
+ ByteCopy(&(psShape->dfXMax), pabyRec + 16, 8);
+ ByteCopy(&(psShape->dfYMax), pabyRec + 24, 8);
- if( bBigEndian )
+ if (bBigEndian)
{
- SwapWord( 8, pabyRec + 0 );
- SwapWord( 8, pabyRec + 8 );
- SwapWord( 8, pabyRec + 16 );
- SwapWord( 8, pabyRec + 24 );
+ SwapWord(8, pabyRec + 0);
+ SwapWord(8, pabyRec + 8);
+ SwapWord(8, pabyRec + 16);
+ SwapWord(8, pabyRec + 24);
}
}
/* SHPCreateObject(). */
/************************************************************************/
-void SHPAPI_CALL
-SHPComputeExtents( SHPObject * psObject )
-
+void SHPAPI_CALL SHPComputeExtents(SHPObject *psObject)
{
- int i;
-
-/* -------------------------------------------------------------------- */
-/* Build extents for this object. */
-/* -------------------------------------------------------------------- */
- if( psObject->nVertices > 0 )
+ /* -------------------------------------------------------------------- */
+ /* Build extents for this object. */
+ /* -------------------------------------------------------------------- */
+ if (psObject->nVertices > 0)
{
psObject->dfXMin = psObject->dfXMax = psObject->padfX[0];
psObject->dfYMin = psObject->dfYMax = psObject->padfY[0];
psObject->dfMMin = psObject->dfMMax = psObject->padfM[0];
}
- for( i = 0; i < psObject->nVertices; i++ )
+ for (int i = 0; i < psObject->nVertices; i++)
{
psObject->dfXMin = MIN(psObject->dfXMin, psObject->padfX[i]);
psObject->dfYMin = MIN(psObject->dfYMin, psObject->padfY[i]);
/************************************************************************/
SHPObject SHPAPI_CALL1(*)
-SHPCreateObject( int nSHPType, int nShapeId, int nParts,
- const int * panPartStart, const int * panPartType,
- int nVertices, const double *padfX, const double *padfY,
- const double * padfZ, const double * padfM )
-
+ SHPCreateObject(int nSHPType, int nShapeId, int nParts,
+ const int *panPartStart, const int *panPartType,
+ int nVertices, const double *padfX, const double *padfY,
+ const double *padfZ, const double *padfM)
{
- SHPObject *psObject;
- int i, bHasM, bHasZ;
-
- psObject = STATIC_CAST(SHPObject *, calloc(1,sizeof(SHPObject)));
+ SHPObject *psObject =
+ STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject)));
psObject->nSHPType = nSHPType;
psObject->nShapeId = nShapeId;
psObject->bMeasureIsUsed = FALSE;
-/* -------------------------------------------------------------------- */
-/* Establish whether this shape type has M, and Z values. */
-/* -------------------------------------------------------------------- */
- if( nSHPType == SHPT_ARCM
- || nSHPType == SHPT_POINTM
- || nSHPType == SHPT_POLYGONM
- || nSHPType == SHPT_MULTIPOINTM )
+ /* -------------------------------------------------------------------- */
+ /* Establish whether this shape type has M, and Z values. */
+ /* -------------------------------------------------------------------- */
+ bool bHasM;
+ bool bHasZ;
+
+ if (nSHPType == SHPT_ARCM || nSHPType == SHPT_POINTM ||
+ nSHPType == SHPT_POLYGONM || nSHPType == SHPT_MULTIPOINTM)
{
- bHasM = TRUE;
- bHasZ = FALSE;
+ bHasM = true;
+ bHasZ = false;
}
- else if( nSHPType == SHPT_ARCZ
- || nSHPType == SHPT_POINTZ
- || nSHPType == SHPT_POLYGONZ
- || nSHPType == SHPT_MULTIPOINTZ
- || nSHPType == SHPT_MULTIPATCH )
+ else if (nSHPType == SHPT_ARCZ || nSHPType == SHPT_POINTZ ||
+ nSHPType == SHPT_POLYGONZ || nSHPType == SHPT_MULTIPOINTZ ||
+ nSHPType == SHPT_MULTIPATCH)
{
- bHasM = TRUE;
- bHasZ = TRUE;
+ bHasM = true;
+ bHasZ = true;
}
else
{
- bHasM = FALSE;
- bHasZ = FALSE;
+ bHasM = false;
+ bHasZ = false;
}
-/* -------------------------------------------------------------------- */
-/* Capture parts. Note that part type is optional, and */
-/* defaults to ring. */
-/* -------------------------------------------------------------------- */
- if( nSHPType == SHPT_ARC || nSHPType == SHPT_POLYGON
- || nSHPType == SHPT_ARCM || nSHPType == SHPT_POLYGONM
- || nSHPType == SHPT_ARCZ || nSHPType == SHPT_POLYGONZ
- || nSHPType == SHPT_MULTIPATCH )
+ /* -------------------------------------------------------------------- */
+ /* Capture parts. Note that part type is optional, and */
+ /* defaults to ring. */
+ /* -------------------------------------------------------------------- */
+ if (nSHPType == SHPT_ARC || nSHPType == SHPT_POLYGON ||
+ nSHPType == SHPT_ARCM || nSHPType == SHPT_POLYGONM ||
+ nSHPType == SHPT_ARCZ || nSHPType == SHPT_POLYGONZ ||
+ nSHPType == SHPT_MULTIPATCH)
{
- psObject->nParts = MAX(1,nParts);
+ psObject->nParts = MAX(1, nParts);
- psObject->panPartStart = STATIC_CAST(int *,
- calloc(sizeof(int), psObject->nParts));
- psObject->panPartType = STATIC_CAST(int *,
- malloc(sizeof(int) * psObject->nParts));
+ psObject->panPartStart =
+ STATIC_CAST(int *, calloc(sizeof(int), psObject->nParts));
+ psObject->panPartType =
+ STATIC_CAST(int *, malloc(sizeof(int) * psObject->nParts));
psObject->panPartStart[0] = 0;
psObject->panPartType[0] = SHPP_RING;
- for( i = 0; i < nParts; i++ )
+ for (int i = 0; i < nParts; i++)
{
- if( panPartStart != SHPLIB_NULLPTR )
+ if (panPartStart != SHPLIB_NULLPTR)
psObject->panPartStart[i] = panPartStart[i];
- if( panPartType != SHPLIB_NULLPTR )
+ if (panPartType != SHPLIB_NULLPTR)
psObject->panPartType[i] = panPartType[i];
else
psObject->panPartType[i] = SHPP_RING;
}
- if( psObject->panPartStart[0] != 0 )
+ if (psObject->panPartStart[0] != 0)
psObject->panPartStart[0] = 0;
}
-/* -------------------------------------------------------------------- */
-/* Capture vertices. Note that X, Y, Z and M are optional. */
-/* -------------------------------------------------------------------- */
- if( nVertices > 0 )
- {
- size_t nSize = sizeof(double) * nVertices;
- psObject->padfX = STATIC_CAST(double *, padfX ? malloc(nSize) :
- calloc(sizeof(double),nVertices));
- psObject->padfY = STATIC_CAST(double *, padfY ? malloc(nSize) :
- calloc(sizeof(double),nVertices));
- psObject->padfZ = STATIC_CAST(double *, padfZ && bHasZ ? malloc(nSize) :
- calloc(sizeof(double),nVertices));
- psObject->padfM = STATIC_CAST(double *, padfM && bHasM ? malloc(nSize) :
- calloc(sizeof(double),nVertices));
- if( padfX != SHPLIB_NULLPTR )
+ /* -------------------------------------------------------------------- */
+ /* Capture vertices. Note that X, Y, Z and M are optional. */
+ /* -------------------------------------------------------------------- */
+ if (nVertices > 0)
+ {
+ const size_t nSize = sizeof(double) * nVertices;
+ psObject->padfX =
+ STATIC_CAST(double *, padfX ? malloc(nSize)
+ : calloc(sizeof(double), nVertices));
+ psObject->padfY =
+ STATIC_CAST(double *, padfY ? malloc(nSize)
+ : calloc(sizeof(double), nVertices));
+ psObject->padfZ = STATIC_CAST(
+ double *,
+ padfZ &&bHasZ ? malloc(nSize) : calloc(sizeof(double), nVertices));
+ psObject->padfM = STATIC_CAST(
+ double *,
+ padfM &&bHasM ? malloc(nSize) : calloc(sizeof(double), nVertices));
+ if (padfX != SHPLIB_NULLPTR)
memcpy(psObject->padfX, padfX, nSize);
- if( padfY != SHPLIB_NULLPTR )
+ if (padfY != SHPLIB_NULLPTR)
memcpy(psObject->padfY, padfY, nSize);
- if( padfZ != SHPLIB_NULLPTR && bHasZ )
+ if (padfZ != SHPLIB_NULLPTR && bHasZ)
memcpy(psObject->padfZ, padfZ, nSize);
- if( padfM != SHPLIB_NULLPTR && bHasM )
+ if (padfM != SHPLIB_NULLPTR && bHasM)
{
memcpy(psObject->padfM, padfM, nSize);
psObject->bMeasureIsUsed = TRUE;
}
}
-/* -------------------------------------------------------------------- */
-/* Compute the extents. */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* Compute the extents. */
+ /* -------------------------------------------------------------------- */
psObject->nVertices = nVertices;
- SHPComputeExtents( psObject );
+ SHPComputeExtents(psObject);
- return( psObject );
+ return (psObject);
}
/************************************************************************/
/************************************************************************/
SHPObject SHPAPI_CALL1(*)
-SHPCreateSimpleObject( int nSHPType, int nVertices,
- const double * padfX, const double * padfY,
- const double * padfZ )
-
+ SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX,
+ const double *padfY, const double *padfZ)
{
- return( SHPCreateObject( nSHPType, -1, 0, SHPLIB_NULLPTR, SHPLIB_NULLPTR,
- nVertices, padfX, padfY, padfZ, SHPLIB_NULLPTR ) );
+ return (SHPCreateObject(nSHPType, -1, 0, SHPLIB_NULLPTR, SHPLIB_NULLPTR,
+ nVertices, padfX, padfY, padfZ, SHPLIB_NULLPTR));
}
/************************************************************************/
/* only possible to write vertices at the end of the file. */
/************************************************************************/
-int SHPAPI_CALL
-SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
-
+int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId,
+ SHPObject *psObject)
{
- unsigned int nRecordOffset, nRecordSize=0;
- int i;
- uchar *pabyRec;
- int32 i32;
- int bAppendToLastRecord = FALSE;
- int bAppendToFile = FALSE;
-
psSHP->bUpdated = TRUE;
-/* -------------------------------------------------------------------- */
-/* Ensure that shape object matches the type of the file it is */
-/* being written to. */
-/* -------------------------------------------------------------------- */
- assert( psObject->nSHPType == psSHP->nShapeType
- || psObject->nSHPType == SHPT_NULL );
-
-/* -------------------------------------------------------------------- */
-/* Ensure that -1 is used for appends. Either blow an */
-/* assertion, or if they are disabled, set the shapeid to -1 */
-/* for appends. */
-/* -------------------------------------------------------------------- */
- assert( nShapeId == -1
- || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
-
- if( nShapeId != -1 && nShapeId >= psSHP->nRecords )
+ /* -------------------------------------------------------------------- */
+ /* Ensure that shape object matches the type of the file it is */
+ /* being written to. */
+ /* -------------------------------------------------------------------- */
+ assert(psObject->nSHPType == psSHP->nShapeType ||
+ psObject->nSHPType == SHPT_NULL);
+
+ /* -------------------------------------------------------------------- */
+ /* Ensure that -1 is used for appends. Either blow an */
+ /* assertion, or if they are disabled, set the shapeid to -1 */
+ /* for appends. */
+ /* -------------------------------------------------------------------- */
+ assert(nShapeId == -1 || (nShapeId >= 0 && nShapeId < psSHP->nRecords));
+
+ if (nShapeId != -1 && nShapeId >= psSHP->nRecords)
nShapeId = -1;
-/* -------------------------------------------------------------------- */
-/* Add the new entity to the in memory index. */
-/* -------------------------------------------------------------------- */
- if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
+ /* -------------------------------------------------------------------- */
+ /* Add the new entity to the in memory index. */
+ /* -------------------------------------------------------------------- */
+ if (nShapeId == -1 && psSHP->nRecords + 1 > psSHP->nMaxRecords)
{
+ /* This cannot overflow given that we check that the file size does
+ * not grow over 4 GB, and the minimum size of a record is 12 bytes,
+ * hence the maximm value for nMaxRecords is 357,913,941
+ */
int nNewMaxRecords = psSHP->nMaxRecords + psSHP->nMaxRecords / 3 + 100;
- unsigned int* panRecOffsetNew;
- unsigned int* panRecSizeNew;
+ unsigned int *panRecOffsetNew;
+ unsigned int *panRecSizeNew;
- panRecOffsetNew = STATIC_CAST(unsigned int *,
- SfRealloc(psSHP->panRecOffset,sizeof(unsigned int) * nNewMaxRecords ));
- if( panRecOffsetNew == SHPLIB_NULLPTR )
+ panRecOffsetNew = STATIC_CAST(
+ unsigned int *, realloc(psSHP->panRecOffset,
+ sizeof(unsigned int) * nNewMaxRecords));
+ if (panRecOffsetNew == SHPLIB_NULLPTR)
+ {
+ psSHP->sHooks.Error("Failed to write shape object. "
+ "Memory allocation error.");
return -1;
+ }
psSHP->panRecOffset = panRecOffsetNew;
- panRecSizeNew = STATIC_CAST(unsigned int *,
- SfRealloc(psSHP->panRecSize,sizeof(unsigned int) * nNewMaxRecords ));
- if( panRecSizeNew == SHPLIB_NULLPTR )
+ panRecSizeNew = STATIC_CAST(
+ unsigned int *,
+ realloc(psSHP->panRecSize, sizeof(unsigned int) * nNewMaxRecords));
+ if (panRecSizeNew == SHPLIB_NULLPTR)
+ {
+ psSHP->sHooks.Error("Failed to write shape object. "
+ "Memory allocation error.");
return -1;
+ }
psSHP->panRecSize = panRecSizeNew;
psSHP->nMaxRecords = nNewMaxRecords;
}
-/* -------------------------------------------------------------------- */
-/* Initialize record. */
-/* -------------------------------------------------------------------- */
- pabyRec = STATIC_CAST(uchar *, malloc(psObject->nVertices * 4 * sizeof(double)
- + psObject->nParts * 8 + 128));
- if( pabyRec == SHPLIB_NULLPTR )
- return -1;
+ /* -------------------------------------------------------------------- */
+ /* Initialize record. */
+ /* -------------------------------------------------------------------- */
-/* -------------------------------------------------------------------- */
-/* Extract vertices for a Polygon or Arc. */
-/* -------------------------------------------------------------------- */
- if( psObject->nSHPType == SHPT_POLYGON
- || psObject->nSHPType == SHPT_POLYGONZ
- || psObject->nSHPType == SHPT_POLYGONM
- || psObject->nSHPType == SHPT_ARC
- || psObject->nSHPType == SHPT_ARCZ
- || psObject->nSHPType == SHPT_ARCM
- || psObject->nSHPType == SHPT_MULTIPATCH )
+ /* The following computation cannot overflow on 32-bit platforms given that
+ * the user had to allocate arrays of at least that size. */
+ size_t nRecMaxSize =
+ psObject->nVertices * 4 * sizeof(double) + psObject->nParts * 8;
+ /* But the following test could trigger on 64-bit platforms on huge
+ * geometries. */
+ const unsigned nExtraSpaceForGeomHeader = 128;
+ if (nRecMaxSize > UINT_MAX - nExtraSpaceForGeomHeader)
+ {
+ psSHP->sHooks.Error("Failed to write shape object. Too big geometry.");
+ return -1;
+ }
+ nRecMaxSize += nExtraSpaceForGeomHeader;
+ unsigned char *pabyRec = STATIC_CAST(unsigned char *, malloc(nRecMaxSize));
+ if (pabyRec == SHPLIB_NULLPTR)
{
- int32 nPoints, nParts;
+ psSHP->sHooks.Error("Failed to write shape object. "
+ "Memory allocation error.");
+ return -1;
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Extract vertices for a Polygon or Arc. */
+ /* -------------------------------------------------------------------- */
+ unsigned int nRecordSize = 0;
+ const bool bFirstFeature = psSHP->nRecords == 0;
- nPoints = psObject->nVertices;
- nParts = psObject->nParts;
+ if (psObject->nSHPType == SHPT_POLYGON ||
+ psObject->nSHPType == SHPT_POLYGONZ ||
+ psObject->nSHPType == SHPT_POLYGONM || psObject->nSHPType == SHPT_ARC ||
+ psObject->nSHPType == SHPT_ARCZ || psObject->nSHPType == SHPT_ARCM ||
+ psObject->nSHPType == SHPT_MULTIPATCH)
+ {
+ uint32_t nPoints = psObject->nVertices;
+ uint32_t nParts = psObject->nParts;
- _SHPSetBounds( pabyRec + 12, psObject );
+ _SHPSetBounds(pabyRec + 12, psObject);
- if( bBigEndian ) SwapWord( 4, &nPoints );
- if( bBigEndian ) SwapWord( 4, &nParts );
+ if (bBigEndian)
+ SwapWord(4, &nPoints);
+ if (bBigEndian)
+ SwapWord(4, &nParts);
- ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
- ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
+ ByteCopy(&nPoints, pabyRec + 40 + 8, 4);
+ ByteCopy(&nParts, pabyRec + 36 + 8, 4);
nRecordSize = 52;
/*
* Write part start positions.
*/
- ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
- 4 * psObject->nParts );
- for( i = 0; i < psObject->nParts; i++ )
+ ByteCopy(psObject->panPartStart, pabyRec + 44 + 8,
+ 4 * psObject->nParts);
+ for (int i = 0; i < psObject->nParts; i++)
{
- if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
+ if (bBigEndian)
+ SwapWord(4, pabyRec + 44 + 8 + 4 * i);
nRecordSize += 4;
}
/*
* Write multipatch part types if needed.
*/
- if( psObject->nSHPType == SHPT_MULTIPATCH )
+ if (psObject->nSHPType == SHPT_MULTIPATCH)
{
- memcpy( pabyRec + nRecordSize, psObject->panPartType,
- 4*psObject->nParts );
- for( i = 0; i < psObject->nParts; i++ )
+ memcpy(pabyRec + nRecordSize, psObject->panPartType,
+ 4 * psObject->nParts);
+ for (int i = 0; i < psObject->nParts; i++)
{
- if( bBigEndian ) SwapWord( 4, pabyRec + nRecordSize );
+ if (bBigEndian)
+ SwapWord(4, pabyRec + nRecordSize);
nRecordSize += 4;
}
}
/*
* Write the (x,y) vertex values.
*/
- for( i = 0; i < psObject->nVertices; i++ )
+ for (int i = 0; i < psObject->nVertices; i++)
{
- ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
- ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
+ ByteCopy(psObject->padfX + i, pabyRec + nRecordSize, 8);
+ ByteCopy(psObject->padfY + i, pabyRec + nRecordSize + 8, 8);
- if( bBigEndian )
- SwapWord( 8, pabyRec + nRecordSize );
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
- if( bBigEndian )
- SwapWord( 8, pabyRec + nRecordSize + 8 );
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize + 8);
nRecordSize += 2 * 8;
}
/*
* Write the Z coordinates (if any).
*/
- if( psObject->nSHPType == SHPT_POLYGONZ
- || psObject->nSHPType == SHPT_ARCZ
- || psObject->nSHPType == SHPT_MULTIPATCH )
+ if (psObject->nSHPType == SHPT_POLYGONZ ||
+ psObject->nSHPType == SHPT_ARCZ ||
+ psObject->nSHPType == SHPT_MULTIPATCH)
{
- ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(&(psObject->dfZMin), pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
- ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(&(psObject->dfZMax), pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
- for( i = 0; i < psObject->nVertices; i++ )
+ for (int i = 0; i < psObject->nVertices; i++)
{
- ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(psObject->padfZ + i, pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
}
}
/*
* Write the M values, if any.
*/
- if( psObject->bMeasureIsUsed
- && (psObject->nSHPType == SHPT_POLYGONM
- || psObject->nSHPType == SHPT_ARCM
+ if (psObject->bMeasureIsUsed &&
+ (psObject->nSHPType == SHPT_POLYGONM ||
+ psObject->nSHPType == SHPT_ARCM
#ifndef DISABLE_MULTIPATCH_MEASURE
- || psObject->nSHPType == SHPT_MULTIPATCH
+ || psObject->nSHPType == SHPT_MULTIPATCH
#endif
- || psObject->nSHPType == SHPT_POLYGONZ
- || psObject->nSHPType == SHPT_ARCZ) )
+ || psObject->nSHPType == SHPT_POLYGONZ ||
+ psObject->nSHPType == SHPT_ARCZ))
{
- ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(&(psObject->dfMMin), pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
- ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(&(psObject->dfMMax), pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
- for( i = 0; i < psObject->nVertices; i++ )
+ for (int i = 0; i < psObject->nVertices; i++)
{
- ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(psObject->padfM + i, pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
}
}
}
-/* -------------------------------------------------------------------- */
-/* Extract vertices for a MultiPoint. */
-/* -------------------------------------------------------------------- */
- else if( psObject->nSHPType == SHPT_MULTIPOINT
- || psObject->nSHPType == SHPT_MULTIPOINTZ
- || psObject->nSHPType == SHPT_MULTIPOINTM )
+ /* -------------------------------------------------------------------- */
+ /* Extract vertices for a MultiPoint. */
+ /* -------------------------------------------------------------------- */
+ else if (psObject->nSHPType == SHPT_MULTIPOINT ||
+ psObject->nSHPType == SHPT_MULTIPOINTZ ||
+ psObject->nSHPType == SHPT_MULTIPOINTM)
{
- int32 nPoints;
+ uint32_t nPoints = psObject->nVertices;
- nPoints = psObject->nVertices;
+ _SHPSetBounds(pabyRec + 12, psObject);
- _SHPSetBounds( pabyRec + 12, psObject );
+ if (bBigEndian)
+ SwapWord(4, &nPoints);
+ ByteCopy(&nPoints, pabyRec + 44, 4);
- if( bBigEndian ) SwapWord( 4, &nPoints );
- ByteCopy( &nPoints, pabyRec + 44, 4 );
-
- for( i = 0; i < psObject->nVertices; i++ )
+ for (int i = 0; i < psObject->nVertices; i++)
{
- ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
- ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
+ ByteCopy(psObject->padfX + i, pabyRec + 48 + i * 16, 8);
+ ByteCopy(psObject->padfY + i, pabyRec + 48 + i * 16 + 8, 8);
- if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
- if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
+ if (bBigEndian)
+ SwapWord(8, pabyRec + 48 + i * 16);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + 48 + i * 16 + 8);
}
nRecordSize = 48 + 16 * psObject->nVertices;
- if( psObject->nSHPType == SHPT_MULTIPOINTZ )
+ if (psObject->nSHPType == SHPT_MULTIPOINTZ)
{
- ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(&(psObject->dfZMin), pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
- ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(&(psObject->dfZMax), pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
- for( i = 0; i < psObject->nVertices; i++ )
+ for (int i = 0; i < psObject->nVertices; i++)
{
- ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(psObject->padfZ + i, pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
}
}
- if( psObject->bMeasureIsUsed
- && (psObject->nSHPType == SHPT_MULTIPOINTZ
- || psObject->nSHPType == SHPT_MULTIPOINTM) )
+ if (psObject->bMeasureIsUsed &&
+ (psObject->nSHPType == SHPT_MULTIPOINTZ ||
+ psObject->nSHPType == SHPT_MULTIPOINTM))
{
- ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(&(psObject->dfMMin), pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
- ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(&(psObject->dfMMax), pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
- for( i = 0; i < psObject->nVertices; i++ )
+ for (int i = 0; i < psObject->nVertices; i++)
{
- ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(psObject->padfM + i, pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
}
}
}
-/* -------------------------------------------------------------------- */
-/* Write point. */
-/* -------------------------------------------------------------------- */
- else if( psObject->nSHPType == SHPT_POINT
- || psObject->nSHPType == SHPT_POINTZ
- || psObject->nSHPType == SHPT_POINTM )
+ /* -------------------------------------------------------------------- */
+ /* Write point. */
+ /* -------------------------------------------------------------------- */
+ else if (psObject->nSHPType == SHPT_POINT ||
+ psObject->nSHPType == SHPT_POINTZ ||
+ psObject->nSHPType == SHPT_POINTM)
{
- ByteCopy( psObject->padfX, pabyRec + 12, 8 );
- ByteCopy( psObject->padfY, pabyRec + 20, 8 );
+ ByteCopy(psObject->padfX, pabyRec + 12, 8);
+ ByteCopy(psObject->padfY, pabyRec + 20, 8);
- if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
- if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
+ if (bBigEndian)
+ SwapWord(8, pabyRec + 12);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + 20);
nRecordSize = 28;
- if( psObject->nSHPType == SHPT_POINTZ )
+ if (psObject->nSHPType == SHPT_POINTZ)
{
- ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(psObject->padfZ, pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
}
- if( psObject->bMeasureIsUsed
- && (psObject->nSHPType == SHPT_POINTZ
- || psObject->nSHPType == SHPT_POINTM) )
+ if (psObject->bMeasureIsUsed && (psObject->nSHPType == SHPT_POINTZ ||
+ psObject->nSHPType == SHPT_POINTM))
{
- ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
- if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
+ ByteCopy(psObject->padfM, pabyRec + nRecordSize, 8);
+ if (bBigEndian)
+ SwapWord(8, pabyRec + nRecordSize);
nRecordSize += 8;
}
}
-/* -------------------------------------------------------------------- */
-/* Not much to do for null geometries. */
-/* -------------------------------------------------------------------- */
- else if( psObject->nSHPType == SHPT_NULL )
+ /* -------------------------------------------------------------------- */
+ /* Not much to do for null geometries. */
+ /* -------------------------------------------------------------------- */
+ else if (psObject->nSHPType == SHPT_NULL)
{
nRecordSize = 12;
}
-
else
{
/* unknown type */
- assert( FALSE );
- }
-
-/* -------------------------------------------------------------------- */
-/* Establish where we are going to put this record. If we are */
-/* rewriting the last record of the file, then we can update it in */
-/* place. Otherwise if rewriting an existing record, and it will */
-/* fit, then put it back where the original came from. Otherwise */
-/* write at the end. */
-/* -------------------------------------------------------------------- */
- if( nShapeId != -1 && psSHP->panRecOffset[nShapeId] +
- psSHP->panRecSize[nShapeId] + 8 == psSHP->nFileSize )
+ assert(false);
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Establish where we are going to put this record. If we are */
+ /* rewriting the last record of the file, then we can update it in */
+ /* place. Otherwise if rewriting an existing record, and it will */
+ /* fit, then put it back where the original came from. Otherwise */
+ /* write at the end. */
+ /* -------------------------------------------------------------------- */
+ SAOffset nRecordOffset;
+ bool bAppendToLastRecord = false;
+ bool bAppendToFile = false;
+ if (nShapeId != -1 &&
+ psSHP->panRecOffset[nShapeId] + psSHP->panRecSize[nShapeId] + 8 ==
+ psSHP->nFileSize)
{
nRecordOffset = psSHP->panRecOffset[nShapeId];
- bAppendToLastRecord = TRUE;
+ bAppendToLastRecord = true;
}
- else if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
+ else if (nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize - 8)
{
- if( psSHP->nFileSize > UINT_MAX - nRecordSize)
+ if (psSHP->nFileSize > UINT_MAX - nRecordSize)
{
- char str[128];
- snprintf( str, sizeof(str), "Failed to write shape object. "
- "File size cannot reach %u + %u.",
- psSHP->nFileSize, nRecordSize );
- str[sizeof(str)-1] = '\0';
- psSHP->sHooks.Error( str );
- free( pabyRec );
+ char str[255];
+ snprintf(str, sizeof(str),
+ "Failed to write shape object. "
+ "The maximum file size of %u has been reached. "
+ "The current record of size %u cannot be added.",
+ psSHP->nFileSize, nRecordSize);
+ str[sizeof(str) - 1] = '\0';
+ psSHP->sHooks.Error(str);
+ free(pabyRec);
return -1;
}
- bAppendToFile = TRUE;
+ bAppendToFile = true;
nRecordOffset = psSHP->nFileSize;
}
else
nRecordOffset = psSHP->panRecOffset[nShapeId];
}
-/* -------------------------------------------------------------------- */
-/* Set the shape type, record number, and record size. */
-/* -------------------------------------------------------------------- */
- i32 = (nShapeId < 0) ? psSHP->nRecords+1 : nShapeId+1; /* record # */
- if( !bBigEndian ) SwapWord( 4, &i32 );
- ByteCopy( &i32, pabyRec, 4 );
+ /* -------------------------------------------------------------------- */
+ /* Set the shape type, record number, and record size. */
+ /* -------------------------------------------------------------------- */
+ uint32_t i32 =
+ (nShapeId < 0) ? psSHP->nRecords + 1 : nShapeId + 1; /* record # */
+ if (!bBigEndian)
+ SwapWord(4, &i32);
+ ByteCopy(&i32, pabyRec, 4);
- i32 = (nRecordSize-8)/2; /* record size */
- if( !bBigEndian ) SwapWord( 4, &i32 );
- ByteCopy( &i32, pabyRec + 4, 4 );
+ i32 = (nRecordSize - 8) / 2; /* record size */
+ if (!bBigEndian)
+ SwapWord(4, &i32);
+ ByteCopy(&i32, pabyRec + 4, 4);
- i32 = psObject->nSHPType; /* shape type */
- if( bBigEndian ) SwapWord( 4, &i32 );
- ByteCopy( &i32, pabyRec + 8, 4 );
+ i32 = psObject->nSHPType; /* shape type */
+ if (bBigEndian)
+ SwapWord(4, &i32);
+ ByteCopy(&i32, pabyRec + 8, 4);
-/* -------------------------------------------------------------------- */
-/* Write out record. */
-/* -------------------------------------------------------------------- */
- if( psSHP->sHooks.FSeek( psSHP->fpSHP, nRecordOffset, 0 ) != 0 )
+ /* -------------------------------------------------------------------- */
+ /* Write out record. */
+ /* -------------------------------------------------------------------- */
+
+ /* -------------------------------------------------------------------- */
+ /* Guard FSeek with check for whether we're already at position; */
+ /* no-op FSeeks defeat network filesystems' write buffering. */
+ /* -------------------------------------------------------------------- */
+ if (psSHP->sHooks.FTell(psSHP->fpSHP) != nRecordOffset)
{
- char szErrorMsg[200];
+ if (psSHP->sHooks.FSeek(psSHP->fpSHP, nRecordOffset, 0) != 0)
+ {
+ char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Error in psSHP->sHooks.FSeek() while writing object to .shp file: %s",
- strerror(errno) );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Error in psSHP->sHooks.FSeek() while writing object to "
+ ".shp file: %s",
+ strerror(errno));
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
- free( pabyRec );
- return -1;
+ free(pabyRec);
+ return -1;
+ }
}
- if( psSHP->sHooks.FWrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
+ if (psSHP->sHooks.FWrite(pabyRec, nRecordSize, 1, psSHP->fpSHP) < 1)
{
char szErrorMsg[200];
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Error in psSHP->sHooks.FWrite() while writing object of %u bytes to .shp file: %s",
- nRecordSize, strerror(errno) );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Error in psSHP->sHooks.FWrite() while writing object of %u "
+ "bytes to .shp file: %s",
+ nRecordSize, strerror(errno));
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
- free( pabyRec );
+ free(pabyRec);
return -1;
}
- free( pabyRec );
+ free(pabyRec);
- if( bAppendToLastRecord )
+ if (bAppendToLastRecord)
{
- psSHP->nFileSize = psSHP->panRecOffset[nShapeId] + nRecordSize;
+ psSHP->nFileSize = psSHP->panRecOffset[nShapeId] + nRecordSize;
}
- else if( bAppendToFile )
+ else if (bAppendToFile)
{
- if( nShapeId == -1 )
+ if (nShapeId == -1)
nShapeId = psSHP->nRecords++;
psSHP->panRecOffset[nShapeId] = psSHP->nFileSize;
psSHP->nFileSize += nRecordSize;
}
- psSHP->panRecSize[nShapeId] = nRecordSize-8;
+ psSHP->panRecSize[nShapeId] = nRecordSize - 8;
-/* -------------------------------------------------------------------- */
-/* Expand file wide bounds based on this shape. */
-/* -------------------------------------------------------------------- */
- if( psSHP->adBoundsMin[0] == 0.0
- && psSHP->adBoundsMax[0] == 0.0
- && psSHP->adBoundsMin[1] == 0.0
- && psSHP->adBoundsMax[1] == 0.0 )
+ /* -------------------------------------------------------------------- */
+ /* Expand file wide bounds based on this shape. */
+ /* -------------------------------------------------------------------- */
+ if (bFirstFeature)
{
- if( psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0 )
+ if (psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0)
{
psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = 0.0;
psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = 0.0;
{
psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
- psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ ? psObject->padfZ[0] : 0.0;
- psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM ? psObject->padfM[0] : 0.0;
+ psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] =
+ psObject->padfZ ? psObject->padfZ[0] : 0.0;
+ psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] =
+ psObject->padfM ? psObject->padfM[0] : 0.0;
}
}
- for( i = 0; i < psObject->nVertices; i++ )
+ for (int i = 0; i < psObject->nVertices; i++)
{
- psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
- psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
- psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
- psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
- if( psObject->padfZ )
+ psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0], psObject->padfX[i]);
+ psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1], psObject->padfY[i]);
+ psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0], psObject->padfX[i]);
+ psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1], psObject->padfY[i]);
+ if (psObject->padfZ)
{
- psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
- psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
+ psSHP->adBoundsMin[2] =
+ MIN(psSHP->adBoundsMin[2], psObject->padfZ[i]);
+ psSHP->adBoundsMax[2] =
+ MAX(psSHP->adBoundsMax[2], psObject->padfZ[i]);
}
- if( psObject->padfM )
+ if (psObject->padfM)
{
- psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
- psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
+ psSHP->adBoundsMin[3] =
+ MIN(psSHP->adBoundsMin[3], psObject->padfM[i]);
+ psSHP->adBoundsMax[3] =
+ MAX(psSHP->adBoundsMax[3], psObject->padfM[i]);
}
}
- return( nShapeId );
+ return (nShapeId);
}
/************************************************************************/
/* SHPAllocBuffer() */
/************************************************************************/
-static void* SHPAllocBuffer(unsigned char** pBuffer, int nSize)
+static void *SHPAllocBuffer(unsigned char **pBuffer, int nSize)
{
- unsigned char* pRet;
-
- if( pBuffer == SHPLIB_NULLPTR )
+ if (pBuffer == SHPLIB_NULLPTR)
return calloc(1, nSize);
- pRet = *pBuffer;
- if( pRet == SHPLIB_NULLPTR )
+ unsigned char *pRet = *pBuffer;
+ if (pRet == SHPLIB_NULLPTR)
return SHPLIB_NULLPTR;
(*pBuffer) += nSize;
/* SHPReallocObjectBufIfNecessary() */
/************************************************************************/
-static unsigned char* SHPReallocObjectBufIfNecessary ( SHPHandle psSHP,
- int nObjectBufSize )
+static unsigned char *SHPReallocObjectBufIfNecessary(SHPHandle psSHP,
+ int nObjectBufSize)
{
- unsigned char* pBuffer;
- if( nObjectBufSize == 0 )
+ if (nObjectBufSize == 0)
{
nObjectBufSize = 4 * sizeof(double);
}
- if( nObjectBufSize > psSHP->nObjectBufSize )
+
+ unsigned char *pBuffer;
+ if (nObjectBufSize > psSHP->nObjectBufSize)
{
- pBuffer = STATIC_CAST(unsigned char*, realloc( psSHP->pabyObjectBuf, nObjectBufSize ));
- if( pBuffer != SHPLIB_NULLPTR )
+ pBuffer = STATIC_CAST(unsigned char *,
+ realloc(psSHP->pabyObjectBuf, nObjectBufSize));
+ if (pBuffer != SHPLIB_NULLPTR)
{
psSHP->pabyObjectBuf = pBuffer;
psSHP->nObjectBufSize = nObjectBufSize;
}
}
else
+ {
pBuffer = psSHP->pabyObjectBuf;
+ }
+
return pBuffer;
}
/************************************************************************/
/* SHPReadObject() */
/* */
-/* Read the vertices, parts, and other non-attribute information */
-/* for one shape. */
+/* Read the vertices, parts, and other non-attribute information */
+/* for one shape. */
/************************************************************************/
-SHPObject SHPAPI_CALL1(*)
-SHPReadObject( SHPHandle psSHP, int hEntity )
-
+SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity)
{
- int nEntitySize, nRequiredSize;
- SHPObject *psShape;
- char szErrorMsg[128];
- int nSHPType;
- int nBytesRead;
-
-/* -------------------------------------------------------------------- */
-/* Validate the record/entity number. */
-/* -------------------------------------------------------------------- */
- if( hEntity < 0 || hEntity >= psSHP->nRecords )
+ /* -------------------------------------------------------------------- */
+ /* Validate the record/entity number. */
+ /* -------------------------------------------------------------------- */
+ if (hEntity < 0 || hEntity >= psSHP->nRecords)
return SHPLIB_NULLPTR;
-/* -------------------------------------------------------------------- */
-/* Read offset/length from SHX loading if necessary. */
-/* -------------------------------------------------------------------- */
- if( psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX != SHPLIB_NULLPTR )
+ /* -------------------------------------------------------------------- */
+ /* Read offset/length from SHX loading if necessary. */
+ /* -------------------------------------------------------------------- */
+ if (psSHP->panRecOffset[hEntity] == 0 && psSHP->fpSHX != SHPLIB_NULLPTR)
{
- unsigned int nOffset, nLength;
+ unsigned int nOffset;
+ unsigned int nLength;
- if( psSHP->sHooks.FSeek( psSHP->fpSHX, 100 + 8 * hEntity, 0 ) != 0 ||
- psSHP->sHooks.FRead( &nOffset, 1, 4, psSHP->fpSHX ) != 4 ||
- psSHP->sHooks.FRead( &nLength, 1, 4, psSHP->fpSHX ) != 4 )
+ if (psSHP->sHooks.FSeek(psSHP->fpSHX, 100 + 8 * hEntity, 0) != 0 ||
+ psSHP->sHooks.FRead(&nOffset, 1, 4, psSHP->fpSHX) != 4 ||
+ psSHP->sHooks.FRead(&nLength, 1, 4, psSHP->fpSHX) != 4)
{
char str[128];
- snprintf( str, sizeof(str),
- "Error in fseek()/fread() reading object from .shx file at offset %d",
- 100 + 8 * hEntity);
- str[sizeof(str)-1] = '\0';
+ snprintf(str, sizeof(str),
+ "Error in fseek()/fread() reading object from .shx file "
+ "at offset %d",
+ 100 + 8 * hEntity);
+ str[sizeof(str) - 1] = '\0';
- psSHP->sHooks.Error( str );
+ psSHP->sHooks.Error(str);
return SHPLIB_NULLPTR;
}
- if( !bBigEndian ) SwapWord( 4, &nOffset );
- if( !bBigEndian ) SwapWord( 4, &nLength );
+ if (!bBigEndian)
+ SwapWord(4, &nOffset);
+ if (!bBigEndian)
+ SwapWord(4, &nLength);
- if( nOffset > STATIC_CAST(unsigned int, INT_MAX) )
+ if (nOffset > STATIC_CAST(unsigned int, INT_MAX))
{
char str[128];
- snprintf( str, sizeof(str),
- "Invalid offset for entity %d", hEntity);
- str[sizeof(str)-1] = '\0';
+ snprintf(str, sizeof(str), "Invalid offset for entity %d", hEntity);
+ str[sizeof(str) - 1] = '\0';
- psSHP->sHooks.Error( str );
+ psSHP->sHooks.Error(str);
return SHPLIB_NULLPTR;
}
- if( nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4) )
+ if (nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4))
{
char str[128];
- snprintf( str, sizeof(str),
- "Invalid length for entity %d", hEntity);
- str[sizeof(str)-1] = '\0';
+ snprintf(str, sizeof(str), "Invalid length for entity %d", hEntity);
+ str[sizeof(str) - 1] = '\0';
- psSHP->sHooks.Error( str );
+ psSHP->sHooks.Error(str);
return SHPLIB_NULLPTR;
}
- psSHP->panRecOffset[hEntity] = nOffset*2;
- psSHP->panRecSize[hEntity] = nLength*2;
+ psSHP->panRecOffset[hEntity] = nOffset * 2;
+ psSHP->panRecSize[hEntity] = nLength * 2;
}
-/* -------------------------------------------------------------------- */
-/* Ensure our record buffer is large enough. */
-/* -------------------------------------------------------------------- */
- nEntitySize = psSHP->panRecSize[hEntity]+8;
- if( nEntitySize > psSHP->nBufSize )
+ /* -------------------------------------------------------------------- */
+ /* Ensure our record buffer is large enough. */
+ /* -------------------------------------------------------------------- */
+ const int nEntitySize = psSHP->panRecSize[hEntity] + 8;
+ if (nEntitySize > psSHP->nBufSize)
{
- uchar* pabyRecNew;
int nNewBufSize = nEntitySize;
- if( nNewBufSize < INT_MAX - nNewBufSize / 3 )
+ if (nNewBufSize < INT_MAX - nNewBufSize / 3)
nNewBufSize += nNewBufSize / 3;
else
nNewBufSize = INT_MAX;
/* Before allocating too much memory, check that the file is big enough */
/* and do not trust the file size in the header the first time we */
/* need to allocate more than 10 MB */
- if( nNewBufSize >= 10 * 1024 * 1024 )
+ if (nNewBufSize >= 10 * 1024 * 1024)
{
- if( psSHP->nBufSize < 10 * 1024 * 1024 )
+ if (psSHP->nBufSize < 10 * 1024 * 1024)
{
SAOffset nFileSize;
- psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 2 );
+ psSHP->sHooks.FSeek(psSHP->fpSHP, 0, 2);
nFileSize = psSHP->sHooks.FTell(psSHP->fpSHP);
- if( nFileSize >= UINT_MAX )
+ if (nFileSize >= UINT_MAX)
psSHP->nFileSize = UINT_MAX;
else
psSHP->nFileSize = STATIC_CAST(unsigned int, nFileSize);
}
- if( psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
+ if (psSHP->panRecOffset[hEntity] >= psSHP->nFileSize ||
/* We should normally use nEntitySize instead of*/
/* psSHP->panRecSize[hEntity] in the below test, but because of */
/* the case of non conformant .shx files detailed a bit below, */
/* let be more tolerant */
- psSHP->panRecSize[hEntity] > psSHP->nFileSize - psSHP->panRecOffset[hEntity] )
+ psSHP->panRecSize[hEntity] >
+ psSHP->nFileSize - psSHP->panRecOffset[hEntity])
{
char str[128];
- snprintf( str, sizeof(str),
- "Error in fread() reading object of size %d at offset %u from .shp file",
- nEntitySize, psSHP->panRecOffset[hEntity] );
- str[sizeof(str)-1] = '\0';
+ snprintf(str, sizeof(str),
+ "Error in fread() reading object of size %d at offset "
+ "%u from .shp file",
+ nEntitySize, psSHP->panRecOffset[hEntity]);
+ str[sizeof(str) - 1] = '\0';
- psSHP->sHooks.Error( str );
+ psSHP->sHooks.Error(str);
return SHPLIB_NULLPTR;
}
}
- pabyRecNew = STATIC_CAST(uchar *, SfRealloc(psSHP->pabyRec,nNewBufSize));
+ unsigned char *pabyRecNew =
+ STATIC_CAST(unsigned char *, realloc(psSHP->pabyRec, nNewBufSize));
if (pabyRecNew == SHPLIB_NULLPTR)
{
- snprintf( szErrorMsg, sizeof(szErrorMsg),
- "Not enough memory to allocate requested memory (nNewBufSize=%d). "
- "Probably broken SHP file", nNewBufSize);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ char szErrorMsg[160];
+ snprintf(szErrorMsg, sizeof(szErrorMsg),
+ "Not enough memory to allocate requested memory "
+ "(nNewBufSize=%d). "
+ "Probably broken SHP file",
+ nNewBufSize);
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
return SHPLIB_NULLPTR;
}
return SHPLIB_NULLPTR;
}
-/* -------------------------------------------------------------------- */
-/* Read the record. */
-/* -------------------------------------------------------------------- */
- if( psSHP->sHooks.FSeek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0 )
+ /* -------------------------------------------------------------------- */
+ /* Read the record. */
+ /* -------------------------------------------------------------------- */
+ if (psSHP->sHooks.FSeek(psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0) != 0)
{
/*
* TODO - mloskot: Consider detailed diagnostics of shape file,
* for example to detect if file is truncated.
*/
char str[128];
- snprintf( str, sizeof(str),
+ snprintf(str, sizeof(str),
"Error in fseek() reading object from .shp file at offset %u",
psSHP->panRecOffset[hEntity]);
- str[sizeof(str)-1] = '\0';
+ str[sizeof(str) - 1] = '\0';
- psSHP->sHooks.Error( str );
+ psSHP->sHooks.Error(str);
return SHPLIB_NULLPTR;
}
- nBytesRead = STATIC_CAST(int, psSHP->sHooks.FRead( psSHP->pabyRec, 1, nEntitySize, psSHP->fpSHP ));
+ const int nBytesRead = STATIC_CAST(
+ int, psSHP->sHooks.FRead(psSHP->pabyRec, 1, nEntitySize, psSHP->fpSHP));
/* Special case for a shapefile whose .shx content length field is not equal */
/* to the content length field of the .shp, which is a violation of "The */
/* file record header." (http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf, page 24) */
/* Actually in that case the .shx content length is equal to the .shp content length + */
/* 4 (16 bit words), representing the 8 bytes of the record header... */
- if( nBytesRead >= 8 && nBytesRead == nEntitySize - 8 )
+ if (nBytesRead >= 8 && nBytesRead == nEntitySize - 8)
{
/* Do a sanity check */
int nSHPContentLength;
- memcpy( &nSHPContentLength, psSHP->pabyRec + 4, 4 );
- if( !bBigEndian ) SwapWord( 4, &(nSHPContentLength) );
- if( nSHPContentLength < 0 ||
- nSHPContentLength > INT_MAX / 2 - 4 ||
- 2 * nSHPContentLength + 8 != nBytesRead )
+ memcpy(&nSHPContentLength, psSHP->pabyRec + 4, 4);
+ if (!bBigEndian)
+ SwapWord(4, &(nSHPContentLength));
+ if (nSHPContentLength < 0 || nSHPContentLength > INT_MAX / 2 - 4 ||
+ 2 * nSHPContentLength + 8 != nBytesRead)
{
char str[128];
- snprintf( str, sizeof(str),
- "Sanity check failed when trying to recover from inconsistent .shx/.shp with shape %d",
- hEntity );
- str[sizeof(str)-1] = '\0';
+ snprintf(str, sizeof(str),
+ "Sanity check failed when trying to recover from "
+ "inconsistent .shx/.shp with shape %d",
+ hEntity);
+ str[sizeof(str) - 1] = '\0';
- psSHP->sHooks.Error( str );
+ psSHP->sHooks.Error(str);
return SHPLIB_NULLPTR;
}
}
- else if( nBytesRead != nEntitySize )
+ else if (nBytesRead != nEntitySize)
{
/*
* TODO - mloskot: Consider detailed diagnostics of shape file,
* for example to detect if file is truncated.
*/
char str[128];
- snprintf( str, sizeof(str),
- "Error in fread() reading object of size %d at offset %u from .shp file",
- nEntitySize, psSHP->panRecOffset[hEntity] );
- str[sizeof(str)-1] = '\0';
+ snprintf(str, sizeof(str),
+ "Error in fread() reading object of size %d at offset %u from "
+ ".shp file",
+ nEntitySize, psSHP->panRecOffset[hEntity]);
+ str[sizeof(str) - 1] = '\0';
- psSHP->sHooks.Error( str );
+ psSHP->sHooks.Error(str);
return SHPLIB_NULLPTR;
}
- if ( 8 + 4 > nEntitySize )
+ if (8 + 4 > nEntitySize)
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
- "Corrupted .shp file : shape %d : nEntitySize = %d",
- hEntity, nEntitySize);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ "Corrupted .shp file : shape %d : nEntitySize = %d", hEntity,
+ nEntitySize);
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
return SHPLIB_NULLPTR;
}
- memcpy( &nSHPType, psSHP->pabyRec + 8, 4 );
+ int nSHPType;
+ memcpy(&nSHPType, psSHP->pabyRec + 8, 4);
- if( bBigEndian ) SwapWord( 4, &(nSHPType) );
+ if (bBigEndian)
+ SwapWord(4, &(nSHPType));
-/* -------------------------------------------------------------------- */
-/* Allocate and minimally initialize the object. */
-/* -------------------------------------------------------------------- */
- if( psSHP->bFastModeReadObject )
+ /* -------------------------------------------------------------------- */
+ /* Allocate and minimally initialize the object. */
+ /* -------------------------------------------------------------------- */
+ SHPObject *psShape;
+ if (psSHP->bFastModeReadObject)
{
- if( psSHP->psCachedObject->bFastModeReadObject )
+ if (psSHP->psCachedObject->bFastModeReadObject)
{
- psSHP->sHooks.Error( "Invalid read pattern in fast read mode. "
- "SHPDestroyObject() should be called." );
+ psSHP->sHooks.Error("Invalid read pattern in fast read mode. "
+ "SHPDestroyObject() should be called.");
return SHPLIB_NULLPTR;
}
memset(psShape, 0, sizeof(SHPObject));
}
else
- psShape = STATIC_CAST(SHPObject *, calloc(1,sizeof(SHPObject)));
+ {
+ psShape = STATIC_CAST(SHPObject *, calloc(1, sizeof(SHPObject)));
+ }
psShape->nShapeId = hEntity;
psShape->nSHPType = nSHPType;
psShape->bMeasureIsUsed = FALSE;
psShape->bFastModeReadObject = psSHP->bFastModeReadObject;
-/* ==================================================================== */
-/* Extract vertices for a Polygon or Arc. */
-/* ==================================================================== */
- if( psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC
- || psShape->nSHPType == SHPT_POLYGONZ
- || psShape->nSHPType == SHPT_POLYGONM
- || psShape->nSHPType == SHPT_ARCZ
- || psShape->nSHPType == SHPT_ARCM
- || psShape->nSHPType == SHPT_MULTIPATCH )
+ /* ==================================================================== */
+ /* Extract vertices for a Polygon or Arc. */
+ /* ==================================================================== */
+ if (psShape->nSHPType == SHPT_POLYGON || psShape->nSHPType == SHPT_ARC ||
+ psShape->nSHPType == SHPT_POLYGONZ ||
+ psShape->nSHPType == SHPT_POLYGONM || psShape->nSHPType == SHPT_ARCZ ||
+ psShape->nSHPType == SHPT_ARCM || psShape->nSHPType == SHPT_MULTIPATCH)
{
- int32 nPoints, nParts;
- int i, nOffset;
- unsigned char* pBuffer = SHPLIB_NULLPTR;
- unsigned char** ppBuffer = SHPLIB_NULLPTR;
-
- if ( 40 + 8 + 4 > nEntitySize )
+ if (40 + 8 + 4 > nEntitySize)
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
"Corrupted .shp file : shape %d : nEntitySize = %d",
hEntity, nEntitySize);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
-/* -------------------------------------------------------------------- */
-/* Get the X/Y bounds. */
-/* -------------------------------------------------------------------- */
- memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
- memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
- memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
- memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
-
- if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
-
-/* -------------------------------------------------------------------- */
-/* Extract part/point count, and build vertex and part arrays */
-/* to proper size. */
-/* -------------------------------------------------------------------- */
- memcpy( &nPoints, psSHP->pabyRec + 40 + 8, 4 );
- memcpy( &nParts, psSHP->pabyRec + 36 + 8, 4 );
-
- if( bBigEndian ) SwapWord( 4, &nPoints );
- if( bBigEndian ) SwapWord( 4, &nParts );
+ /* -------------------------------------------------------------------- */
+ /* Get the X/Y bounds. */
+ /* -------------------------------------------------------------------- */
+ memcpy(&(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8);
+ memcpy(&(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8);
+ memcpy(&(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8);
+ memcpy(&(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8);
+
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfXMin));
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfYMin));
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfXMax));
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfYMax));
+
+ /* -------------------------------------------------------------------- */
+ /* Extract part/point count, and build vertex and part arrays */
+ /* to proper size. */
+ /* -------------------------------------------------------------------- */
+ uint32_t nPoints;
+ memcpy(&nPoints, psSHP->pabyRec + 40 + 8, 4);
+ uint32_t nParts;
+ memcpy(&nParts, psSHP->pabyRec + 36 + 8, 4);
+
+ if (bBigEndian)
+ SwapWord(4, &nPoints);
+ if (bBigEndian)
+ SwapWord(4, &nParts);
/* nPoints and nParts are unsigned */
if (/* nPoints < 0 || nParts < 0 || */
nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
"Corrupted .shp file : shape %d, nPoints=%u, nParts=%u.",
hEntity, nPoints, nParts);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
/* With the previous checks on nPoints and nParts, */
/* we should not overflow here and after */
/* since 50 M * (16 + 8 + 8) = 1 600 MB */
- nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
- if ( psShape->nSHPType == SHPT_POLYGONZ
- || psShape->nSHPType == SHPT_ARCZ
- || psShape->nSHPType == SHPT_MULTIPATCH )
+ int nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
+ if (psShape->nSHPType == SHPT_POLYGONZ ||
+ psShape->nSHPType == SHPT_ARCZ ||
+ psShape->nSHPType == SHPT_MULTIPATCH)
{
nRequiredSize += 16 + 8 * nPoints;
}
- if( psShape->nSHPType == SHPT_MULTIPATCH )
+ if (psShape->nSHPType == SHPT_MULTIPATCH)
{
nRequiredSize += 4 * nParts;
}
if (nRequiredSize > nEntitySize)
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
- "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, nEntitySize=%d.",
+ "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, "
+ "nEntitySize=%d.",
hEntity, nPoints, nParts, nEntitySize);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
- if( psShape->bFastModeReadObject )
+ unsigned char *pBuffer = SHPLIB_NULLPTR;
+ unsigned char **ppBuffer = SHPLIB_NULLPTR;
+
+ if (psShape->bFastModeReadObject)
{
- int nObjectBufSize = 4 * sizeof(double) * nPoints + 2 * sizeof(int) * nParts;
+ const int nObjectBufSize =
+ 4 * sizeof(double) * nPoints + 2 * sizeof(int) * nParts;
pBuffer = SHPReallocObjectBufIfNecessary(psSHP, nObjectBufSize);
ppBuffer = &pBuffer;
}
psShape->nVertices = nPoints;
- psShape->padfX = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
- psShape->padfY = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
- psShape->padfZ = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
- psShape->padfM = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+ psShape->padfX = STATIC_CAST(
+ double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+ psShape->padfY = STATIC_CAST(
+ double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+ psShape->padfZ = STATIC_CAST(
+ double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+ psShape->padfM = STATIC_CAST(
+ double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
psShape->nParts = nParts;
- psShape->panPartStart = STATIC_CAST(int *, SHPAllocBuffer(ppBuffer, nParts * sizeof(int)));
- psShape->panPartType = STATIC_CAST(int *, SHPAllocBuffer(ppBuffer, nParts * sizeof(int)));
+ psShape->panPartStart =
+ STATIC_CAST(int *, SHPAllocBuffer(ppBuffer, nParts * sizeof(int)));
+ psShape->panPartType =
+ STATIC_CAST(int *, SHPAllocBuffer(ppBuffer, nParts * sizeof(int)));
if (psShape->padfX == SHPLIB_NULLPTR ||
psShape->padfY == SHPLIB_NULLPTR ||
psShape->panPartStart == SHPLIB_NULLPTR ||
psShape->panPartType == SHPLIB_NULLPTR)
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
- "Not enough memory to allocate requested memory (nPoints=%u, nParts=%u) for shape %d. "
- "Probably broken SHP file", nPoints, nParts, hEntity );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ "Not enough memory to allocate requested memory "
+ "(nPoints=%u, nParts=%u) for shape %d. "
+ "Probably broken SHP file",
+ nPoints, nParts, hEntity);
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
- for( i = 0; STATIC_CAST(int32, i) < nParts; i++ )
+ for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++)
psShape->panPartType[i] = SHPP_RING;
-/* -------------------------------------------------------------------- */
-/* Copy out the part array from the record. */
-/* -------------------------------------------------------------------- */
- memcpy( psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts );
- for( i = 0; STATIC_CAST(int32, i) < nParts; i++ )
+ /* -------------------------------------------------------------------- */
+ /* Copy out the part array from the record. */
+ /* -------------------------------------------------------------------- */
+ memcpy(psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts);
+ for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++)
{
- if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
+ if (bBigEndian)
+ SwapWord(4, psShape->panPartStart + i);
/* We check that the offset is inside the vertex array */
- if (psShape->panPartStart[i] < 0
- || (psShape->panPartStart[i] >= psShape->nVertices
- && psShape->nVertices > 0)
- || (psShape->panPartStart[i] > 0 && psShape->nVertices == 0) )
+ if (psShape->panPartStart[i] < 0 ||
+ (psShape->panPartStart[i] >= psShape->nVertices &&
+ psShape->nVertices > 0) ||
+ (psShape->panPartStart[i] > 0 && psShape->nVertices == 0))
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
- "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
- hEntity, i, psShape->panPartStart[i], psShape->nVertices);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ "Corrupted .shp file : shape %d : panPartStart[%d] = "
+ "%d, nVertices = %d",
+ hEntity, i, psShape->panPartStart[i],
+ psShape->nVertices);
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
- if (i > 0 && psShape->panPartStart[i] <= psShape->panPartStart[i-1])
+ if (i > 0 &&
+ psShape->panPartStart[i] <= psShape->panPartStart[i - 1])
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
- "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
- hEntity, i, psShape->panPartStart[i], i - 1, psShape->panPartStart[i - 1]);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ "Corrupted .shp file : shape %d : panPartStart[%d] = "
+ "%d, panPartStart[%d] = %d",
+ hEntity, i, psShape->panPartStart[i], i - 1,
+ psShape->panPartStart[i - 1]);
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
}
- nOffset = 44 + 8 + 4*nParts;
+ int nOffset = 44 + 8 + 4 * nParts;
-/* -------------------------------------------------------------------- */
-/* If this is a multipatch, we will also have parts types. */
-/* -------------------------------------------------------------------- */
- if( psShape->nSHPType == SHPT_MULTIPATCH )
+ /* -------------------------------------------------------------------- */
+ /* If this is a multipatch, we will also have parts types. */
+ /* -------------------------------------------------------------------- */
+ if (psShape->nSHPType == SHPT_MULTIPATCH)
{
- memcpy( psShape->panPartType, psSHP->pabyRec + nOffset, 4*nParts );
- for( i = 0; STATIC_CAST(int32, i) < nParts; i++ )
+ memcpy(psShape->panPartType, psSHP->pabyRec + nOffset, 4 * nParts);
+ for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++)
{
- if( bBigEndian ) SwapWord( 4, psShape->panPartType+i );
+ if (bBigEndian)
+ SwapWord(4, psShape->panPartType + i);
}
- nOffset += 4*nParts;
+ nOffset += 4 * nParts;
}
-/* -------------------------------------------------------------------- */
-/* Copy out the vertices from the record. */
-/* -------------------------------------------------------------------- */
- for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+ /* -------------------------------------------------------------------- */
+ /* Copy out the vertices from the record. */
+ /* -------------------------------------------------------------------- */
+ for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
- memcpy(psShape->padfX + i,
- psSHP->pabyRec + nOffset + i * 16,
- 8 );
+ memcpy(psShape->padfX + i, psSHP->pabyRec + nOffset + i * 16, 8);
- memcpy(psShape->padfY + i,
- psSHP->pabyRec + nOffset + i * 16 + 8,
- 8 );
+ memcpy(psShape->padfY + i, psSHP->pabyRec + nOffset + i * 16 + 8,
+ 8);
- if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
- if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+ if (bBigEndian)
+ SwapWord(8, psShape->padfX + i);
+ if (bBigEndian)
+ SwapWord(8, psShape->padfY + i);
}
- nOffset += 16*nPoints;
+ nOffset += 16 * nPoints;
-/* -------------------------------------------------------------------- */
-/* If we have a Z coordinate, collect that now. */
-/* -------------------------------------------------------------------- */
- if( psShape->nSHPType == SHPT_POLYGONZ
- || psShape->nSHPType == SHPT_ARCZ
- || psShape->nSHPType == SHPT_MULTIPATCH )
+ /* -------------------------------------------------------------------- */
+ /* If we have a Z coordinate, collect that now. */
+ /* -------------------------------------------------------------------- */
+ if (psShape->nSHPType == SHPT_POLYGONZ ||
+ psShape->nSHPType == SHPT_ARCZ ||
+ psShape->nSHPType == SHPT_MULTIPATCH)
{
- memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
- memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
+ memcpy(&(psShape->dfZMin), psSHP->pabyRec + nOffset, 8);
+ memcpy(&(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8);
- if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfZMin));
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfZMax));
- for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+ for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
- memcpy( psShape->padfZ + i,
- psSHP->pabyRec + nOffset + 16 + i*8, 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
+ memcpy(psShape->padfZ + i,
+ psSHP->pabyRec + nOffset + 16 + i * 8, 8);
+ if (bBigEndian)
+ SwapWord(8, psShape->padfZ + i);
}
- nOffset += 16 + 8*nPoints;
+ nOffset += 16 + 8 * nPoints;
}
- else if( psShape->bFastModeReadObject )
+ else if (psShape->bFastModeReadObject)
{
psShape->padfZ = SHPLIB_NULLPTR;
}
-/* -------------------------------------------------------------------- */
-/* If we have a M measure value, then read it now. We assume */
-/* that the measure can be present for any shape if the size is */
-/* big enough, but really it will only occur for the Z shapes */
-/* (options), and the M shapes. */
-/* -------------------------------------------------------------------- */
- if( nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8*nPoints) )
+ /* -------------------------------------------------------------------- */
+ /* If we have a M measure value, then read it now. We assume */
+ /* that the measure can be present for any shape if the size is */
+ /* big enough, but really it will only occur for the Z shapes */
+ /* (options), and the M shapes. */
+ /* -------------------------------------------------------------------- */
+ if (nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8 * nPoints))
{
- memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
- memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
+ memcpy(&(psShape->dfMMin), psSHP->pabyRec + nOffset, 8);
+ memcpy(&(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8);
- if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfMMin));
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfMMax));
- for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+ for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
- memcpy( psShape->padfM + i,
- psSHP->pabyRec + nOffset + 16 + i*8, 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
+ memcpy(psShape->padfM + i,
+ psSHP->pabyRec + nOffset + 16 + i * 8, 8);
+ if (bBigEndian)
+ SwapWord(8, psShape->padfM + i);
}
psShape->bMeasureIsUsed = TRUE;
}
- else if( psShape->bFastModeReadObject )
+ else if (psShape->bFastModeReadObject)
{
psShape->padfM = SHPLIB_NULLPTR;
}
}
-/* ==================================================================== */
-/* Extract vertices for a MultiPoint. */
-/* ==================================================================== */
- else if( psShape->nSHPType == SHPT_MULTIPOINT
- || psShape->nSHPType == SHPT_MULTIPOINTM
- || psShape->nSHPType == SHPT_MULTIPOINTZ )
+ /* ==================================================================== */
+ /* Extract vertices for a MultiPoint. */
+ /* ==================================================================== */
+ else if (psShape->nSHPType == SHPT_MULTIPOINT ||
+ psShape->nSHPType == SHPT_MULTIPOINTM ||
+ psShape->nSHPType == SHPT_MULTIPOINTZ)
{
- int32 nPoints;
- int i, nOffset;
- unsigned char* pBuffer = SHPLIB_NULLPTR;
- unsigned char** ppBuffer = SHPLIB_NULLPTR;
-
- if ( 44 + 4 > nEntitySize )
+ if (44 + 4 > nEntitySize)
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
"Corrupted .shp file : shape %d : nEntitySize = %d",
hEntity, nEntitySize);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
- memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
+ uint32_t nPoints;
+ memcpy(&nPoints, psSHP->pabyRec + 44, 4);
- if( bBigEndian ) SwapWord( 4, &nPoints );
+ if (bBigEndian)
+ SwapWord(4, &nPoints);
/* nPoints is unsigned */
if (/* nPoints < 0 || */ nPoints > 50 * 1000 * 1000)
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
- "Corrupted .shp file : shape %d : nPoints = %u",
- hEntity, nPoints);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ "Corrupted .shp file : shape %d : nPoints = %u", hEntity,
+ nPoints);
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
- nRequiredSize = 48 + nPoints * 16;
- if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+ int nRequiredSize = 48 + nPoints * 16;
+ if (psShape->nSHPType == SHPT_MULTIPOINTZ)
{
nRequiredSize += 16 + nPoints * 8;
}
if (nRequiredSize > nEntitySize)
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
- "Corrupted .shp file : shape %d : nPoints = %u, nEntitySize = %d",
+ "Corrupted .shp file : shape %d : nPoints = %u, "
+ "nEntitySize = %d",
hEntity, nPoints, nEntitySize);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
- if( psShape->bFastModeReadObject )
+ unsigned char *pBuffer = SHPLIB_NULLPTR;
+ unsigned char **ppBuffer = SHPLIB_NULLPTR;
+
+ if (psShape->bFastModeReadObject)
{
- int nObjectBufSize = 4 * sizeof(double) * nPoints;
+ const int nObjectBufSize = 4 * sizeof(double) * nPoints;
pBuffer = SHPReallocObjectBufIfNecessary(psSHP, nObjectBufSize);
ppBuffer = &pBuffer;
}
psShape->nVertices = nPoints;
- psShape->padfX = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
- psShape->padfY = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
- psShape->padfZ = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
- psShape->padfM = STATIC_CAST(double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+ psShape->padfX = STATIC_CAST(
+ double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+ psShape->padfY = STATIC_CAST(
+ double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+ psShape->padfZ = STATIC_CAST(
+ double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
+ psShape->padfM = STATIC_CAST(
+ double *, SHPAllocBuffer(ppBuffer, sizeof(double) * nPoints));
if (psShape->padfX == SHPLIB_NULLPTR ||
psShape->padfY == SHPLIB_NULLPTR ||
psShape->padfZ == SHPLIB_NULLPTR ||
psShape->padfM == SHPLIB_NULLPTR)
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
- "Not enough memory to allocate requested memory (nPoints=%u) for shape %d. "
- "Probably broken SHP file", nPoints, hEntity );
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ "Not enough memory to allocate requested memory "
+ "(nPoints=%u) for shape %d. "
+ "Probably broken SHP file",
+ nPoints, hEntity);
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
- for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+ for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
- memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
- memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
+ memcpy(psShape->padfX + i, psSHP->pabyRec + 48 + 16 * i, 8);
+ memcpy(psShape->padfY + i, psSHP->pabyRec + 48 + 16 * i + 8, 8);
- if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
- if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
+ if (bBigEndian)
+ SwapWord(8, psShape->padfX + i);
+ if (bBigEndian)
+ SwapWord(8, psShape->padfY + i);
}
- nOffset = 48 + 16*nPoints;
+ int nOffset = 48 + 16 * nPoints;
-/* -------------------------------------------------------------------- */
-/* Get the X/Y bounds. */
-/* -------------------------------------------------------------------- */
- memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 );
- memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
- memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
- memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
+ /* -------------------------------------------------------------------- */
+ /* Get the X/Y bounds. */
+ /* -------------------------------------------------------------------- */
+ memcpy(&(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8);
+ memcpy(&(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8);
+ memcpy(&(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8);
+ memcpy(&(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8);
- if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfXMin));
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfYMin));
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfXMax));
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfYMax));
-/* -------------------------------------------------------------------- */
-/* If we have a Z coordinate, collect that now. */
-/* -------------------------------------------------------------------- */
- if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+ /* -------------------------------------------------------------------- */
+ /* If we have a Z coordinate, collect that now. */
+ /* -------------------------------------------------------------------- */
+ if (psShape->nSHPType == SHPT_MULTIPOINTZ)
{
- memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
- memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
+ memcpy(&(psShape->dfZMin), psSHP->pabyRec + nOffset, 8);
+ memcpy(&(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8);
- if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfZMin));
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfZMax));
- for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+ for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
- memcpy( psShape->padfZ + i,
- psSHP->pabyRec + nOffset + 16 + i*8, 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
+ memcpy(psShape->padfZ + i,
+ psSHP->pabyRec + nOffset + 16 + i * 8, 8);
+ if (bBigEndian)
+ SwapWord(8, psShape->padfZ + i);
}
- nOffset += 16 + 8*nPoints;
+ nOffset += 16 + 8 * nPoints;
}
- else if( psShape->bFastModeReadObject )
+ else if (psShape->bFastModeReadObject)
psShape->padfZ = SHPLIB_NULLPTR;
-/* -------------------------------------------------------------------- */
-/* If we have a M measure value, then read it now. We assume */
-/* that the measure can be present for any shape if the size is */
-/* big enough, but really it will only occur for the Z shapes */
-/* (options), and the M shapes. */
-/* -------------------------------------------------------------------- */
- if( nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8*nPoints) )
+ /* -------------------------------------------------------------------- */
+ /* If we have a M measure value, then read it now. We assume */
+ /* that the measure can be present for any shape if the size is */
+ /* big enough, but really it will only occur for the Z shapes */
+ /* (options), and the M shapes. */
+ /* -------------------------------------------------------------------- */
+ if (nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8 * nPoints))
{
- memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
- memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
+ memcpy(&(psShape->dfMMin), psSHP->pabyRec + nOffset, 8);
+ memcpy(&(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8);
- if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
- if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfMMin));
+ if (bBigEndian)
+ SwapWord(8, &(psShape->dfMMax));
- for( i = 0; STATIC_CAST(int32, i) < nPoints; i++ )
+ for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
- memcpy( psShape->padfM + i,
- psSHP->pabyRec + nOffset + 16 + i*8, 8 );
- if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
+ memcpy(psShape->padfM + i,
+ psSHP->pabyRec + nOffset + 16 + i * 8, 8);
+ if (bBigEndian)
+ SwapWord(8, psShape->padfM + i);
}
psShape->bMeasureIsUsed = TRUE;
}
- else if( psShape->bFastModeReadObject )
+ else if (psShape->bFastModeReadObject)
psShape->padfM = SHPLIB_NULLPTR;
}
-/* ==================================================================== */
-/* Extract vertices for a point. */
-/* ==================================================================== */
- else if( psShape->nSHPType == SHPT_POINT
- || psShape->nSHPType == SHPT_POINTM
- || psShape->nSHPType == SHPT_POINTZ )
+ /* ==================================================================== */
+ /* Extract vertices for a point. */
+ /* ==================================================================== */
+ else if (psShape->nSHPType == SHPT_POINT ||
+ psShape->nSHPType == SHPT_POINTM ||
+ psShape->nSHPType == SHPT_POINTZ)
{
- int nOffset;
-
psShape->nVertices = 1;
- if( psShape->bFastModeReadObject )
+ if (psShape->bFastModeReadObject)
{
psShape->padfX = &(psShape->dfXMin);
psShape->padfY = &(psShape->dfYMin);
}
else
{
- psShape->padfX = STATIC_CAST(double *, calloc(1,sizeof(double)));
- psShape->padfY = STATIC_CAST(double *, calloc(1,sizeof(double)));
- psShape->padfZ = STATIC_CAST(double *, calloc(1,sizeof(double)));
- psShape->padfM = STATIC_CAST(double *, calloc(1,sizeof(double)));
+ psShape->padfX = STATIC_CAST(double *, calloc(1, sizeof(double)));
+ psShape->padfY = STATIC_CAST(double *, calloc(1, sizeof(double)));
+ psShape->padfZ = STATIC_CAST(double *, calloc(1, sizeof(double)));
+ psShape->padfM = STATIC_CAST(double *, calloc(1, sizeof(double)));
}
- if (20 + 8 + (( psShape->nSHPType == SHPT_POINTZ ) ? 8 : 0)> nEntitySize)
+ if (20 + 8 + ((psShape->nSHPType == SHPT_POINTZ) ? 8 : 0) > nEntitySize)
{
+ char szErrorMsg[160];
snprintf(szErrorMsg, sizeof(szErrorMsg),
"Corrupted .shp file : shape %d : nEntitySize = %d",
hEntity, nEntitySize);
- szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
- psSHP->sHooks.Error( szErrorMsg );
+ szErrorMsg[sizeof(szErrorMsg) - 1] = '\0';
+ psSHP->sHooks.Error(szErrorMsg);
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
- memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
- memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
+ memcpy(psShape->padfX, psSHP->pabyRec + 12, 8);
+ memcpy(psShape->padfY, psSHP->pabyRec + 20, 8);
- if( bBigEndian ) SwapWord( 8, psShape->padfX );
- if( bBigEndian ) SwapWord( 8, psShape->padfY );
+ if (bBigEndian)
+ SwapWord(8, psShape->padfX);
+ if (bBigEndian)
+ SwapWord(8, psShape->padfY);
- nOffset = 20 + 8;
+ int nOffset = 20 + 8;
-/* -------------------------------------------------------------------- */
-/* If we have a Z coordinate, collect that now. */
-/* -------------------------------------------------------------------- */
- if( psShape->nSHPType == SHPT_POINTZ )
+ /* -------------------------------------------------------------------- */
+ /* If we have a Z coordinate, collect that now. */
+ /* -------------------------------------------------------------------- */
+ if (psShape->nSHPType == SHPT_POINTZ)
{
- memcpy( psShape->padfZ, psSHP->pabyRec + nOffset, 8 );
+ memcpy(psShape->padfZ, psSHP->pabyRec + nOffset, 8);
- if( bBigEndian ) SwapWord( 8, psShape->padfZ );
+ if (bBigEndian)
+ SwapWord(8, psShape->padfZ);
nOffset += 8;
}
-/* -------------------------------------------------------------------- */
-/* If we have a M measure value, then read it now. We assume */
-/* that the measure can be present for any shape if the size is */
-/* big enough, but really it will only occur for the Z shapes */
-/* (options), and the M shapes. */
-/* -------------------------------------------------------------------- */
- if( nEntitySize >= nOffset + 8 )
+ /* -------------------------------------------------------------------- */
+ /* If we have a M measure value, then read it now. We assume */
+ /* that the measure can be present for any shape if the size is */
+ /* big enough, but really it will only occur for the Z shapes */
+ /* (options), and the M shapes. */
+ /* -------------------------------------------------------------------- */
+ if (nEntitySize >= nOffset + 8)
{
- memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
+ memcpy(psShape->padfM, psSHP->pabyRec + nOffset, 8);
- if( bBigEndian ) SwapWord( 8, psShape->padfM );
+ if (bBigEndian)
+ SwapWord(8, psShape->padfM);
psShape->bMeasureIsUsed = TRUE;
}
-/* -------------------------------------------------------------------- */
-/* Since no extents are supplied in the record, we will apply */
-/* them from the single vertex. */
-/* -------------------------------------------------------------------- */
+ /* -------------------------------------------------------------------- */
+ /* Since no extents are supplied in the record, we will apply */
+ /* them from the single vertex. */
+ /* -------------------------------------------------------------------- */
psShape->dfXMin = psShape->dfXMax = psShape->padfX[0];
psShape->dfYMin = psShape->dfYMax = psShape->padfY[0];
psShape->dfZMin = psShape->dfZMax = psShape->padfZ[0];
psShape->dfMMin = psShape->dfMMax = psShape->padfM[0];
}
- return( psShape );
+ return (psShape);
}
/************************************************************************/
/* SHPTypeName() */
/************************************************************************/
-const char SHPAPI_CALL1(*)
-SHPTypeName( int nSHPType )
-
+const char SHPAPI_CALL1(*) SHPTypeName(int nSHPType)
{
- switch( nSHPType )
+ switch (nSHPType)
{
- case SHPT_NULL:
- return "NullShape";
+ case SHPT_NULL:
+ return "NullShape";
- case SHPT_POINT:
- return "Point";
+ case SHPT_POINT:
+ return "Point";
- case SHPT_ARC:
- return "Arc";
+ case SHPT_ARC:
+ return "Arc";
- case SHPT_POLYGON:
- return "Polygon";
+ case SHPT_POLYGON:
+ return "Polygon";
- case SHPT_MULTIPOINT:
- return "MultiPoint";
+ case SHPT_MULTIPOINT:
+ return "MultiPoint";
- case SHPT_POINTZ:
- return "PointZ";
+ case SHPT_POINTZ:
+ return "PointZ";
- case SHPT_ARCZ:
- return "ArcZ";
+ case SHPT_ARCZ:
+ return "ArcZ";
- case SHPT_POLYGONZ:
- return "PolygonZ";
+ case SHPT_POLYGONZ:
+ return "PolygonZ";
- case SHPT_MULTIPOINTZ:
- return "MultiPointZ";
+ case SHPT_MULTIPOINTZ:
+ return "MultiPointZ";
- case SHPT_POINTM:
- return "PointM";
+ case SHPT_POINTM:
+ return "PointM";
- case SHPT_ARCM:
- return "ArcM";
+ case SHPT_ARCM:
+ return "ArcM";
- case SHPT_POLYGONM:
- return "PolygonM";
+ case SHPT_POLYGONM:
+ return "PolygonM";
- case SHPT_MULTIPOINTM:
- return "MultiPointM";
+ case SHPT_MULTIPOINTM:
+ return "MultiPointM";
- case SHPT_MULTIPATCH:
- return "MultiPatch";
+ case SHPT_MULTIPATCH:
+ return "MultiPatch";
- default:
- return "UnknownShapeType";
+ default:
+ return "UnknownShapeType";
}
}
/* SHPPartTypeName() */
/************************************************************************/
-const char SHPAPI_CALL1(*)
-SHPPartTypeName( int nPartType )
-
+const char SHPAPI_CALL1(*) SHPPartTypeName(int nPartType)
{
- switch( nPartType )
+ switch (nPartType)
{
- case SHPP_TRISTRIP:
- return "TriangleStrip";
+ case SHPP_TRISTRIP:
+ return "TriangleStrip";
- case SHPP_TRIFAN:
- return "TriangleFan";
+ case SHPP_TRIFAN:
+ return "TriangleFan";
- case SHPP_OUTERRING:
- return "OuterRing";
+ case SHPP_OUTERRING:
+ return "OuterRing";
- case SHPP_INNERRING:
- return "InnerRing";
+ case SHPP_INNERRING:
+ return "InnerRing";
- case SHPP_FIRSTRING:
- return "FirstRing";
+ case SHPP_FIRSTRING:
+ return "FirstRing";
- case SHPP_RING:
- return "Ring";
+ case SHPP_RING:
+ return "Ring";
- default:
- return "UnknownPartType";
+ default:
+ return "UnknownPartType";
}
}
/* SHPDestroyObject() */
/************************************************************************/
-void SHPAPI_CALL
-SHPDestroyObject( SHPObject * psShape )
-
+void SHPAPI_CALL SHPDestroyObject(SHPObject *psShape)
{
- if( psShape == SHPLIB_NULLPTR )
+ if (psShape == SHPLIB_NULLPTR)
return;
- if( psShape->bFastModeReadObject )
+ if (psShape->bFastModeReadObject)
{
psShape->bFastModeReadObject = FALSE;
return;
}
- if( psShape->padfX != SHPLIB_NULLPTR )
- free( psShape->padfX );
- if( psShape->padfY != SHPLIB_NULLPTR )
- free( psShape->padfY );
- if( psShape->padfZ != SHPLIB_NULLPTR )
- free( psShape->padfZ );
- if( psShape->padfM != SHPLIB_NULLPTR )
- free( psShape->padfM );
+ if (psShape->padfX != SHPLIB_NULLPTR)
+ free(psShape->padfX);
+ if (psShape->padfY != SHPLIB_NULLPTR)
+ free(psShape->padfY);
+ if (psShape->padfZ != SHPLIB_NULLPTR)
+ free(psShape->padfZ);
+ if (psShape->padfM != SHPLIB_NULLPTR)
+ free(psShape->padfM);
- if( psShape->panPartStart != SHPLIB_NULLPTR )
- free( psShape->panPartStart );
- if( psShape->panPartType != SHPLIB_NULLPTR )
- free( psShape->panPartType );
+ if (psShape->panPartStart != SHPLIB_NULLPTR)
+ free(psShape->panPartStart);
+ if (psShape->panPartType != SHPLIB_NULLPTR)
+ free(psShape->panPartType);
- free( psShape );
+ free(psShape);
}
/************************************************************************/
/* SHPGetPartVertexCount() */
/************************************************************************/
-static int SHPGetPartVertexCount( const SHPObject * psObject, int iPart )
+static int SHPGetPartVertexCount(const SHPObject *psObject, int iPart)
{
- if( iPart == psObject->nParts-1 )
+ if (iPart == psObject->nParts - 1)
return psObject->nVertices - psObject->panPartStart[iPart];
else
- return psObject->panPartStart[iPart+1] - psObject->panPartStart[iPart];
+ return psObject->panPartStart[iPart + 1] -
+ psObject->panPartStart[iPart];
}
/************************************************************************/
/* SHPRewindIsInnerRing() */
/************************************************************************/
-static int SHPRewindIsInnerRing( const SHPObject * psObject,
- int iOpRing )
+/* Return -1 in case of ambiguity */
+static int SHPRewindIsInnerRing(const SHPObject *psObject, int iOpRing,
+ double dfTestX, double dfTestY,
+ double dfRelativeTolerance, int bSameZ,
+ double dfTestZ)
{
-/* -------------------------------------------------------------------- */
-/* Determine if this ring is an inner ring or an outer ring */
-/* relative to all the other rings. For now we assume the */
-/* first ring is outer and all others are inner, but eventually */
-/* we need to fix this to handle multiple island polygons and */
-/* unordered sets of rings. */
-/* */
-/* -------------------------------------------------------------------- */
-
- /* Use point in the middle of segment to avoid testing
- * common points of rings.
- */
- const int iOpRingStart = psObject->panPartStart[iOpRing];
- double dfTestX = ( psObject->padfX[iOpRingStart] +
- psObject->padfX[iOpRingStart + 1] ) / 2;
- double dfTestY = ( psObject->padfY[iOpRingStart] +
- psObject->padfY[iOpRingStart + 1] ) / 2;
-
- int bInner = FALSE;
- int iCheckRing;
- for( iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++ )
- {
- int nVertStartCheck, nVertCountCheck;
- int iEdge;
-
- if( iCheckRing == iOpRing )
+ /* -------------------------------------------------------------------- */
+ /* Determine if this ring is an inner ring or an outer ring */
+ /* relative to all the other rings. For now we assume the */
+ /* first ring is outer and all others are inner, but eventually */
+ /* we need to fix this to handle multiple island polygons and */
+ /* unordered sets of rings. */
+ /* */
+ /* -------------------------------------------------------------------- */
+
+ bool bInner = false;
+ for (int iCheckRing = 0; iCheckRing < psObject->nParts; iCheckRing++)
+ {
+ if (iCheckRing == iOpRing)
continue;
- nVertStartCheck = psObject->panPartStart[iCheckRing];
- nVertCountCheck = SHPGetPartVertexCount(psObject, iCheckRing);
+ const int nVertStartCheck = psObject->panPartStart[iCheckRing];
+ const int nVertCountCheck = SHPGetPartVertexCount(psObject, iCheckRing);
- for( iEdge = 0; iEdge < nVertCountCheck; iEdge++ )
+ /* Ignore rings that don't have the same (constant) Z value as the
+ * point. */
+ /* As noted in SHPRewindObject(), this is a simplification */
+ /* of what we should ideally do. */
+ if (!bSameZ)
{
- int iNext;
+ int bZTestOK = TRUE;
+ for (int iVert = nVertStartCheck + 1;
+ iVert < nVertStartCheck + nVertCountCheck; ++iVert)
+ {
+ if (psObject->padfZ[iVert] != dfTestZ)
+ {
+ bZTestOK = FALSE;
+ break;
+ }
+ }
+ if (!bZTestOK)
+ continue;
+ }
- if( iEdge < nVertCountCheck-1 )
- iNext = iEdge+1;
+ for (int iEdge = 0; iEdge < nVertCountCheck; iEdge++)
+ {
+ int iNext;
+ if (iEdge < nVertCountCheck - 1)
+ iNext = iEdge + 1;
else
iNext = 0;
+ const double y0 = psObject->padfY[iEdge + nVertStartCheck];
+ const double y1 = psObject->padfY[iNext + nVertStartCheck];
/* Rule #1:
* Test whether the edge 'straddles' the horizontal ray from
* the test point (dfTestY,dfTestY)
* The rule #1 also excludes edges colinear with the ray.
*/
- if ( ( psObject->padfY[iEdge+nVertStartCheck] < dfTestY
- && dfTestY <= psObject->padfY[iNext+nVertStartCheck] )
- || ( psObject->padfY[iNext+nVertStartCheck] < dfTestY
- && dfTestY <= psObject->padfY[iEdge+nVertStartCheck] ) )
+ if ((y0 < dfTestY && dfTestY <= y1) ||
+ (y1 < dfTestY && dfTestY <= y0))
{
/* Rule #2:
* Test if edge-ray intersection is on the right from the
* test point (dfTestY,dfTestY)
*/
- double const intersect =
- ( psObject->padfX[iEdge+nVertStartCheck]
- + ( dfTestY - psObject->padfY[iEdge+nVertStartCheck] )
- / ( psObject->padfY[iNext+nVertStartCheck] -
- psObject->padfY[iEdge+nVertStartCheck] )
- * ( psObject->padfX[iNext+nVertStartCheck] -
- psObject->padfX[iEdge+nVertStartCheck] ) );
-
- if (intersect < dfTestX)
+ const double x0 = psObject->padfX[iEdge + nVertStartCheck];
+ const double x1 = psObject->padfX[iNext + nVertStartCheck];
+ const double intersect_minus_testX =
+ (x0 - dfTestX) + (dfTestY - y0) / (y1 - y0) * (x1 - x0);
+
+ if (fabs(intersect_minus_testX) <=
+ dfRelativeTolerance * fabs(dfTestX))
+ {
+ /* Potential shared edge, or slightly overlapping polygons
+ */
+ return -1;
+ }
+ else if (intersect_minus_testX < 0)
{
bInner = !bInner;
}
/* specification. */
/************************************************************************/
-int SHPAPI_CALL
-SHPRewindObject( CPL_UNUSED SHPHandle hSHP,
- SHPObject * psObject )
+int SHPAPI_CALL SHPRewindObject(CPL_UNUSED SHPHandle hSHP, SHPObject *psObject)
{
- int iOpRing, bAltered = 0;
-
-/* -------------------------------------------------------------------- */
-/* Do nothing if this is not a polygon object. */
-/* -------------------------------------------------------------------- */
- if( psObject->nSHPType != SHPT_POLYGON
- && psObject->nSHPType != SHPT_POLYGONZ
- && psObject->nSHPType != SHPT_POLYGONM )
+ /* -------------------------------------------------------------------- */
+ /* Do nothing if this is not a polygon object. */
+ /* -------------------------------------------------------------------- */
+ if (psObject->nSHPType != SHPT_POLYGON &&
+ psObject->nSHPType != SHPT_POLYGONZ &&
+ psObject->nSHPType != SHPT_POLYGONM)
return 0;
- if( psObject->nVertices == 0 || psObject->nParts == 0 )
+ if (psObject->nVertices == 0 || psObject->nParts == 0)
return 0;
-/* -------------------------------------------------------------------- */
-/* Process each of the rings. */
-/* -------------------------------------------------------------------- */
- for( iOpRing = 0; iOpRing < psObject->nParts; iOpRing++ )
+ /* -------------------------------------------------------------------- */
+ /* Test if all points have the same Z value. */
+ /* -------------------------------------------------------------------- */
+ int bSameZ = TRUE;
+ if (psObject->nSHPType == SHPT_POLYGONZ ||
+ psObject->nSHPType == SHPT_POLYGONM)
{
- int bInner, iVert, nVertCount, nVertStart;
- double dfSum;
+ for (int iVert = 1; iVert < psObject->nVertices; ++iVert)
+ {
+ if (psObject->padfZ[iVert] != psObject->padfZ[0])
+ {
+ bSameZ = FALSE;
+ break;
+ }
+ }
+ }
- nVertStart = psObject->panPartStart[iOpRing];
- nVertCount = SHPGetPartVertexCount(psObject, iOpRing);
+ /* -------------------------------------------------------------------- */
+ /* Process each of the rings. */
+ /* -------------------------------------------------------------------- */
+ int bAltered = 0;
+ for (int iOpRing = 0; iOpRing < psObject->nParts; iOpRing++)
+ {
+ const int nVertStart = psObject->panPartStart[iOpRing];
+ const int nVertCount = SHPGetPartVertexCount(psObject, iOpRing);
if (nVertCount < 2)
continue;
- bInner = SHPRewindIsInnerRing(psObject, iOpRing);
-
-/* -------------------------------------------------------------------- */
-/* Determine the current order of this ring so we will know if */
-/* it has to be reversed. */
-/* -------------------------------------------------------------------- */
+ /* If a ring has a non-constant Z value, then consider it as an outer */
+ /* ring. */
+ /* NOTE: this is a rough approximation. If we were smarter, */
+ /* we would check that all points of the ring are coplanar, and compare
+ */
+ /* that to other rings in the same (oblique) plane. */
+ int bDoIsInnerRingTest = TRUE;
+ if (!bSameZ)
+ {
+ int bPartSameZ = TRUE;
+ for (int iVert = nVertStart + 1; iVert < nVertStart + nVertCount;
+ ++iVert)
+ {
+ if (psObject->padfZ[iVert] != psObject->padfZ[nVertStart])
+ {
+ bPartSameZ = FALSE;
+ break;
+ }
+ }
+ if (!bPartSameZ)
+ bDoIsInnerRingTest = FALSE;
+ }
- dfSum = psObject->padfX[nVertStart] *
- (psObject->padfY[nVertStart+1] -
- psObject->padfY[nVertStart+nVertCount-1]);
- for( iVert = nVertStart + 1; iVert < nVertStart+nVertCount-1; iVert++ )
+ int bInner = FALSE;
+ if (bDoIsInnerRingTest)
{
- dfSum += psObject->padfX[iVert] * (psObject->padfY[iVert+1] -
- psObject->padfY[iVert-1]);
+ for (int iTolerance = 0; iTolerance < 2; iTolerance++)
+ {
+ /* In a first attempt, use a relaxed criterion to decide if a
+ * point */
+ /* is inside another ring. If all points of the current ring are
+ * in the */
+ /* "grey" zone w.r.t that criterion, which seems really
+ * unlikely, */
+ /* then use the strict criterion for another pass. */
+ const double dfRelativeTolerance = (iTolerance == 0) ? 1e-9 : 0;
+ for (int iVert = nVertStart;
+ iVert + 1 < nVertStart + nVertCount; ++iVert)
+ {
+ /* Use point in the middle of segment to avoid testing
+ * common points of rings.
+ */
+ const double dfTestX =
+ (psObject->padfX[iVert] + psObject->padfX[iVert + 1]) /
+ 2;
+ const double dfTestY =
+ (psObject->padfY[iVert] + psObject->padfY[iVert + 1]) /
+ 2;
+ const double dfTestZ =
+ !bSameZ ? psObject->padfZ[nVertStart] : 0;
+
+ bInner = SHPRewindIsInnerRing(psObject, iOpRing, dfTestX,
+ dfTestY, dfRelativeTolerance,
+ bSameZ, dfTestZ);
+ if (bInner >= 0)
+ break;
+ }
+ if (bInner >= 0)
+ break;
+ }
+ if (bInner < 0)
+ {
+ /* Completely degenerate case. Do not bother touching order. */
+ continue;
+ }
}
- dfSum += psObject->padfX[iVert] * (psObject->padfY[nVertStart] -
- psObject->padfY[iVert-1]);
+ /* -------------------------------------------------------------------- */
+ /* Determine the current order of this ring so we will know if */
+ /* it has to be reversed. */
+ /* -------------------------------------------------------------------- */
-/* -------------------------------------------------------------------- */
-/* Reverse if necessary. */
-/* -------------------------------------------------------------------- */
- if( (dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner) )
+ double dfSum = psObject->padfX[nVertStart] *
+ (psObject->padfY[nVertStart + 1] -
+ psObject->padfY[nVertStart + nVertCount - 1]);
+ int iVert = nVertStart + 1;
+ for (; iVert < nVertStart + nVertCount - 1; iVert++)
{
- int i;
+ dfSum += psObject->padfX[iVert] *
+ (psObject->padfY[iVert + 1] - psObject->padfY[iVert - 1]);
+ }
+ dfSum += psObject->padfX[iVert] *
+ (psObject->padfY[nVertStart] - psObject->padfY[iVert - 1]);
+
+ /* -------------------------------------------------------------------- */
+ /* Reverse if necessary. */
+ /* -------------------------------------------------------------------- */
+ if ((dfSum < 0.0 && bInner) || (dfSum > 0.0 && !bInner))
+ {
bAltered++;
- for( i = 0; i < nVertCount/2; i++ )
+ for (int i = 0; i < nVertCount / 2; i++)
{
- double dfSaved;
-
/* Swap X */
- dfSaved = psObject->padfX[nVertStart+i];
- psObject->padfX[nVertStart+i] =
- psObject->padfX[nVertStart+nVertCount-i-1];
- psObject->padfX[nVertStart+nVertCount-i-1] = dfSaved;
+ double dfSaved = psObject->padfX[nVertStart + i];
+ psObject->padfX[nVertStart + i] =
+ psObject->padfX[nVertStart + nVertCount - i - 1];
+ psObject->padfX[nVertStart + nVertCount - i - 1] = dfSaved;
/* Swap Y */
- dfSaved = psObject->padfY[nVertStart+i];
- psObject->padfY[nVertStart+i] =
- psObject->padfY[nVertStart+nVertCount-i-1];
- psObject->padfY[nVertStart+nVertCount-i-1] = dfSaved;
+ dfSaved = psObject->padfY[nVertStart + i];
+ psObject->padfY[nVertStart + i] =
+ psObject->padfY[nVertStart + nVertCount - i - 1];
+ psObject->padfY[nVertStart + nVertCount - i - 1] = dfSaved;
/* Swap Z */
- if( psObject->padfZ )
+ if (psObject->padfZ)
{
- dfSaved = psObject->padfZ[nVertStart+i];
- psObject->padfZ[nVertStart+i] =
- psObject->padfZ[nVertStart+nVertCount-i-1];
- psObject->padfZ[nVertStart+nVertCount-i-1] = dfSaved;
+ dfSaved = psObject->padfZ[nVertStart + i];
+ psObject->padfZ[nVertStart + i] =
+ psObject->padfZ[nVertStart + nVertCount - i - 1];
+ psObject->padfZ[nVertStart + nVertCount - i - 1] = dfSaved;
}
/* Swap M */
- if( psObject->padfM )
+ if (psObject->padfM)
{
- dfSaved = psObject->padfM[nVertStart+i];
- psObject->padfM[nVertStart+i] =
- psObject->padfM[nVertStart+nVertCount-i-1];
- psObject->padfM[nVertStart+nVertCount-i-1] = dfSaved;
+ dfSaved = psObject->padfM[nVertStart + i];
+ psObject->padfM[nVertStart + i] =
+ psObject->padfM[nVertStart + nVertCount - i - 1];
+ psObject->padfM[nVertStart + nVertCount - i - 1] = dfSaved;
}
}
}